Commit ecf40581 by banice

用户中心部分添加,未完成订单和充值订单

parent 47f580c4
......@@ -38,7 +38,7 @@ class PublishToTopic extends BaseApi
/**
* @var int
*/
private $qos = 0;
private $qos = 1;
public function __construct()
......
......@@ -11,7 +11,7 @@ namespace Lib\command;
class OpenDoor implements Command
{
private $command = '11';
private $command = 11;
private $boxNum = 0;
......@@ -21,41 +21,53 @@ class OpenDoor implements Command
private $operation = 1;
private $operationType = 1;
private $boxId = 0;
private $doorId = 0;
public function getMessage(): string
{
return json_encode([
'command' => $this->command,
'doors' => [
'box_num' => $this->boxNum,
'door_num' => $this->doorNum,
'order_id' => $this->orderId,
'operation' => $this->operation
'command' => (int)$this->command,
'hdg_topic' => 'open_door',
'doors' => [
'box_num' => $this->boxNum,
'door_num' => $this->doorNum,
'order_id' => $this->orderId,
'operation' => $this->operation,
'door_id' => $this->doorId,
'box_id' => $this->boxId,
'operation_type' => $this->operationType,
]
]);
}
/**
* @return string
* @return int
*/
public function getCommand(): string
public function getCommand(): int
{
return $this->command;
}
/**
* @param string $command
* @param int $command
*/
public function setCommand(string $command): void
public function setCommand(int $command): void
{
$this->command = $command;
}
/**
* @return int
*/
public function getBoxNum(): int
{
return $this->boxNum;
......@@ -117,5 +129,53 @@ class OpenDoor implements Command
$this->operation = $operation;
}
/**
* @return int
*/
public function getOperationType(): int
{
return $this->operationType;
}
/**
* @param int $operationType
*/
public function setOperationType(int $operationType): void
{
$this->operationType = $operationType;
}
/**
* @return int
*/
public function getBoxId(): int
{
return $this->boxId;
}
/**
* @param int $boxId
*/
public function setBoxId(int $boxId): void
{
$this->boxId = $boxId;
}
/**
* @return int
*/
public function getDoorId(): int
{
return $this->doorId;
}
/**
* @param int $doorId
*/
public function setDoorId(int $doorId): void
{
$this->doorId = $doorId;
}
}
\ No newline at end of file
......@@ -12,7 +12,10 @@ namespace Lib\custom;
use Dingo\Api\Contract\Transformer\Adapter;
use Dingo\Api\Http\Request;
use Dingo\Api\Transformer\Binding;
use Illuminate\Support\Facades\Log;
use Lib\wx\pay\Order;
use Src\Battery;
use Src\wallet\Wallet;
class MyCustomTransformer implements Adapter
{
......@@ -59,6 +62,27 @@ class MyCustomTransformer implements Adapter
];
} else if ($response instanceof Battery) {
if (filled($response->getCode())) {
$data = [
'has_battery' => true,
'power' => $response->getPower(),
'code' => $response->getCode(),
'borrow_date' => $response->getBorrowDate(),
'battery_type' => $response->getBatteryType(),
];
} else {
$data['has_battery'] = false;
}
} else if ($response instanceof Wallet) {
$data = [
'card' => $response->getCard(),
'balance' => $response->getBalance(),
'deposit' => $response->getDeposit(),
];
}
return array_filter([
......
......@@ -18,13 +18,16 @@ use Lib\aliyun\api\PublishToTopic;
use Lib\aliyun\Client;
use Lib\command\OpenDoor;
use Lib\custom\MyCustomTransformer;
use Lib\wx\pay\UnifiedOrder;
use Src\box\Box;
use Src\box\door\Door;
use Src\order\Order;
use Src\order\OrderCache;
use Src\Site;
use Validator;
use Auth;
use Log;
use DB;
class ReplaceController extends Controller
{
......@@ -39,9 +42,27 @@ class ReplaceController extends Controller
if ($validator->fails() === true) {
abort(400, $validator->errors()->first());
}
//todo 检查用户当前是否有正在换电未结束的订单
app()->register(RedisServiceProvider::class);
//todo 检查用户当前是否有正在换电未支付的订单
$userModel = Auth::user();
$userId = $userModel->id;
$userOpenId = $userModel->open_id;
Log::debug($userId);
$orderModel = new OrderModel();
$lastOrder = $orderModel->searchLastOrder($userId);
if (blank($lastOrder)) { // 没有未归还的订单
abort(400, 'user exception without order');
} else {
//尚未归还的订单,微信请求订单支付,返回支付信息
$lastOrder = (array)current($lastOrder);
$order->setOutTradeNo($lastOrder['code']);
}
$boxCode = $request->get('box_code');
$box->setCode($boxCode);
try {
......@@ -49,7 +70,8 @@ class ReplaceController extends Controller
/**
* 查找是否有空的柜门,并占用
*/
$freeDoorId = $box->searchByState($boxCode, Door::STATE['close_free']);
// $freeDoorId = $box->searchByState($boxCode, Door::STATE['close_free']);
$freeDoorId = 1;
} catch (\Exception $exception) {
Log::error($exception->getMessage());
abort(500, $exception->getMessage());
......@@ -61,6 +83,8 @@ class ReplaceController extends Controller
$this->resultMessage = '无空闲舱门';
return $this->response->array($this->getResponseCode());
}
$returnDoor = new Door();
$returnDoor->setId($freeDoorId);
$returnDoorModel = $returnDoor->getDoorModelById(['box_id', 'name']);
......@@ -70,6 +94,8 @@ class ReplaceController extends Controller
}
$returnBoxId = $returnDoorModel->box_id;
$returnDoorName = $returnDoorModel->name;
//fixme
$returnDoorName = 1;
$returnDoor->setName($returnDoorName);
$returnBox = new Box();
$returnBox->setId($returnBoxId);
......@@ -79,31 +105,47 @@ class ReplaceController extends Controller
abort(500, '电柜丢失');
}
$returnBoxName = $returnBox->getValue('box_type');
//fixme
$returnBoxName = 0;
$returnBox->setName($returnBoxName);
$site->setId($returnBox->getValue('site_id'));
$site->setName($returnBox->getValue('site_name'));
$userModel = Auth::user();
$order->setOutTradeNo(rand(1000, 99999) . $site->getId() . time());
$order->setUserId($userModel->id);
$order->setSite($site);
$order->setReturnBox($returnBox);
$order->setReturnDoor($returnDoor);
/**---添加订单---**/
$orderModel = new OrderModel();
$orderModel->initOrder($order);
$orderCache = new OrderCache();
$orderCache->setOrder($order);
$orderCache->update([
'returnBoxId' => $returnBoxId,
'returnDoorId' => $order->getReturnDoor()->getId(),
'userId' => $userId,
'inSiteId' => $site->getId(),
'inSiteName' => $site->getName(),
'openId' => $userOpenId,
]);
/**---发送打开舱门命令---**/
$openDoorCommand = new OpenDoor();
$openDoorCommand->setOrderId($order->getOutTradeNo());
$openDoorCommand->setBoxNum($order->getReturnBox()->getName());
$openDoorCommand->setDoorNum($order->getReturnDoor()->getName());
$openDoorCommand->setDoorId($order->getReturnDoor()->getId());
$openDoorCommand->setBoxId($order->getReturnBox()->getId());
$publishToTopic->setMessageContent($openDoorCommand->getMessage());
$publishToTopic->setProductKey(env('MQTT_PRODUCT_KEY'));
$publishToTopic->setTopicFullName(Box::getOpenDoorTopic($boxCode));
$client->setApi($publishToTopic);
if ($client->request() === true) {
DB::table('orders')->where('code', $order->getOutTradeNo())->update([
'status' => 11,
]);
return $this->response->item($order, new MyCustomTransformer());
} else {
......
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/24
* Time: 上午10:45
*/
namespace App\Http\Controllers\v1\user;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Auth;
use DB;
use Illuminate\Support\Facades\Log;
use Lib\custom\MyCustomTransformer;
use Src\Battery;
use Src\wallet\Coupon;
use Src\wallet\Wallet;
/**
* 个人中心
* Class ProfileController
* @package App\Http\Controllers\v1\user
*/
class ProfileController extends Controller
{
/**
* 获取优惠券
* @param Request $request
*/
public function coupon(Request $request)
{
$coupon = Coupon::authGet();
$couponCount = count($coupon);
if ($couponCount === 0) {
return $this->response->array($this->getResponseCode() + ['data' => ['coupon_count' => 0]]);
} else {
return $this->response->array($this->getResponseCode() + ['data' => ['coupon_count' => $couponCount, 'coupon' => $coupon]]);
}
}
/**
* 我的钱包
* @param Request $request
* @param Wallet $wallet
*/
public function wallet(Request $request, Wallet $wallet)
{
$depositAmount = $wallet->getAuthDeposit();
if ($depositAmount === 0) {
$deposit = [
'has_deposit' => false
];
} else {
$deposit = [
'has_deposit' => true,
'amount' => $depositAmount,
];
}
$balance = $wallet->getAuthBalance();
$cardInfo = $wallet->getAuthCard();
if (blank($cardInfo['card_name']) === true) {
$card['has_card'] = false;
} else {
$card = $cardInfo;
$card['has_card'] = true;
}
$wallet->setCard($card);
$wallet->setDeposit($deposit);
$wallet->setBalance($balance);
return $this->response->item($wallet, new MyCustomTransformer());
}
/**
* 我的电池
* @param Request $request
* @param Battery $battery
* @return \Dingo\Api\Http\Response
*/
public function battery(Request $request, Battery $battery)
{
$userModel = Auth::user();
$userId = $userModel->id;
$batteryCode = $userModel->battery_code;
if (filled($batteryCode) === true) {
$batteryInfo = DB::table('batteries')->where('code', $batteryCode)->first([
'code',
'power',
'battery_type',
'borrow_date',
]);
$battery->setCode($batteryCode);
$battery->setPower($batteryInfo->power);
$battery->setBatteryType($batteryInfo->battery_type);
$battery->setBorrowDate($batteryInfo->borrow_date);
}
return $this->response->item($battery, new MyCustomTransformer());
}
}
\ No newline at end of file
......@@ -11,6 +11,7 @@ namespace App\Http\Controllers\v1\wx\auth;
use App\Http\Controllers\Controller;
use App\model\UserModel;
use App\User;
use Flc\Dysms\Client;
use Flc\Dysms\Request\SendSms;
use Illuminate\Http\Request;
......@@ -35,8 +36,10 @@ class RegisterController extends Controller
{
$validator = Validator::make($request->all(), [
'telephone' => 'required|digits:11',
'code' => 'required|digits:4',
'telephone' => 'required|digits:11',
'code' => 'required|digits:4',
'nickname' => 'required',
'header_url' => 'required'
]);
if ($validator->fails() === true) {
......@@ -58,11 +61,22 @@ class RegisterController extends Controller
if ($userModel === null) {
$userModel = new UserModel();
$userModel->telephone = $telephone;
$userModel->nickname = $request->get('nickname');
$userModel->img = $request->get('header_url');
if ($userModel->save() == false) {
$this->resultCode = 'FAIL';
$this->returnCode = 50001;
return $this->response->array($this->getResponseCode());
}
} else {
UserModel::where('telephone', $telephone)->update([
'nickname' => $request->get('nickname'),
'img' => $request->get('header_url'),
]);
}
$token = Auth::login($userModel);
......@@ -84,8 +98,10 @@ class RegisterController extends Controller
$validator = Validator::make($request->all(), [
'telephone' => 'required|digits:11|exists:guests,telephone',
'code' => 'required|digits:4',
'telephone' => 'required|digits:11',
'code' => 'required|digits:4',
'nickname' => 'required',
'header_url' => 'required|url'
]);
......@@ -102,7 +118,18 @@ class RegisterController extends Controller
}
$userModel = UserModel::where('telephone', $phone)->first();
if ($userModel === null) {
$userModel = new UserModel();
$userModel->nickname = $request->get('nickname');
$userModel->telephone = $phone;
$userModel->img = $request->get('header_url');
$userModel->save();
} else {
UserModel::where('telephone', $phone)->update([
'nickname' => $request->get('nickname'),
'img' => $request->get('header_url'),
]);
}
$token = Auth::login($userModel);
Log::debug($token);
......@@ -113,37 +140,4 @@ class RegisterController extends Controller
}
/**
* 获取注册验证码
* @param Request $request
* @return mixed
*/
public function getCode(Request $request)
{
$validator = Validator::make($request->all(), [
'phone' => 'required|digits:11'
]);
if ($validator->fails() === true) {
abort(400, $validator->errors()->first());
}
$phone = $request->get('phone');
$code = rand(1000, 9999);
$sms = new Sms();
$sms->setTemplateCode('SMS_102895045');
$sms->setSignName('阿里云短信测试专用');
$sms->setPhone($phone);
$sms->setCode($code);
if ($sms->send() === false) {
$this->resultCode = 'FAIL';
$this->resultMessage = $sms->getMessage();
}
return $this->response->array($this->getResponseCode());
}
}
\ No newline at end of file
......@@ -11,6 +11,7 @@ namespace App\model;
use Illuminate\Database\Eloquent\Model;
use Src\order\Order;
use DB;
class OrderModel extends Model
{
......@@ -31,4 +32,12 @@ class OrderModel extends Model
return $this->save();
}
public function searchLastOrder(int $userId)
{
return DB::select('select * from orders where id = (select max(id) from orders where guest_id = ' . $userId . ')');
}
}
\ No newline at end of file
......@@ -10,11 +10,37 @@ namespace App\model;
use Illuminate\Database\Eloquent\Model;
use DB;
class TicketModel extends Model
{
protected $table = 'tickets';
/**
* @param int $userId
* @return int
*/
public function getUserTicket(int $userId): int
{
$today = date('Y-m-d H:i:s');
$ticketId = DB::table('tickets')->where([
['begin_date', '<', $today],
['end_date', '>', $today],
['guest_id', $userId],
['status', 1],
])->min('id');
if (blank($ticketId)) {
return 0;
}
$amount = DB::table('tickets')->where('id', $ticketId)->first(['amount']);
return $amount['amount'];
}
}
\ No newline at end of file
......@@ -34,7 +34,10 @@ class UserModel extends Model implements JWTSubject, AuthenticatableContract, Au
public function getJWTCustomClaims()
{
$return = [
'wx_authorize' => false
'wx_authorize' => false,
'header_url' => $this->img,
'nickname' => $this->nickname,
'telephone' => $this->telephone,
];
if (isset($this->open_id) === true) {
......
......@@ -125,6 +125,8 @@ $app->register(App\Providers\EventServiceProvider::class);
$app->register(Tymon\JWTAuth\Providers\LumenServiceProvider::class);
$app->register(\Overtrue\LaravelLang\TranslationServiceProvider::class);
$app->register(Dingo\Api\Provider\LumenServiceProvider::class);
$app->register(\App\Providers\RedisServiceProvider::class);
if (env('APP_ENV') === 'local') {
$app->register(Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
......
......@@ -18,7 +18,8 @@
"flc/dysms": "^1.0",
"spatie/array-to-xml": "^2.7",
"overtrue/laravel-lang": "^3.0",
"barryvdh/laravel-ide-helper": "^2.5"
"barryvdh/laravel-ide-helper": "^2.5",
"bschmitt/laravel-amqp": "^2.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4c6d57b5e4e40fe8e5706b29ad417cba",
"content-hash": "44821c88ddc8e6c2048f389ea096b891",
"packages": [
{
"name": "barryvdh/laravel-ide-helper",
......@@ -130,6 +130,72 @@
"time": "2016-06-13T19:28:20+00:00"
},
{
"name": "bschmitt/laravel-amqp",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/bschmitt/laravel-amqp.git",
"reference": "e9f83dfcd5feb1fda5648087985c8e62456acd85"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bschmitt/laravel-amqp/zipball/e9f83dfcd5feb1fda5648087985c8e62456acd85",
"reference": "e9f83dfcd5feb1fda5648087985c8e62456acd85",
"shasum": ""
},
"require": {
"illuminate/support": ">=v5.5.28",
"php": ">=7.0",
"php-amqplib/php-amqplib": "2.*"
},
"require-dev": {
"mockery/mockery": "~0.9",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "^3.0@dev"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Bschmitt\\Amqp\\AmqpServiceProvider"
],
"aliases": {
"Amqp": "Bschmitt\\Amqp\\Facades\\Amqp"
}
}
},
"autoload": {
"psr-4": {
"Bschmitt\\Amqp\\": "src/",
"Bschmitt\\Amqp\\Test\\": "test/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Björn Schmitt",
"email": "code@bjoern.io"
}
],
"description": "AMQP wrapper for Laravel and Lumen to publish and consume messages",
"keywords": [
"AMQP",
"Björn Schmitt",
"bschmitt",
"laravel",
"laravel5",
"lumen",
"message queue",
"package",
"queue",
"rabbitmq"
],
"time": "2018-07-13T10:38:45+00:00"
},
{
"name": "caouecs/laravel-lang",
"version": "3.0.54",
"source": {
......@@ -2798,6 +2864,77 @@
"time": "2018-09-03T09:31:08+00:00"
},
{
"name": "php-amqplib/php-amqplib",
"version": "v2.7.2",
"source": {
"type": "git",
"url": "https://github.com/php-amqplib/php-amqplib.git",
"reference": "dfd3694a86f1a7394d3693485259d4074a6ec79b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/dfd3694a86f1a7394d3693485259d4074a6ec79b",
"reference": "dfd3694a86f1a7394d3693485259d4074a6ec79b",
"shasum": ""
},
"require": {
"ext-bcmath": "*",
"ext-mbstring": "*",
"php": ">=5.3.0"
},
"replace": {
"videlalvaro/php-amqplib": "self.version"
},
"require-dev": {
"phpdocumentor/phpdocumentor": "^2.9",
"phpunit/phpunit": "^4.8",
"scrutinizer/ocular": "^1.1",
"squizlabs/php_codesniffer": "^2.5"
},
"suggest": {
"ext-sockets": "Use AMQPSocketConnection"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.7-dev"
}
},
"autoload": {
"psr-4": {
"PhpAmqpLib\\": "PhpAmqpLib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Alvaro Videla",
"role": "Original Maintainer"
},
{
"name": "John Kelly",
"email": "johnmkelly86@gmail.com",
"role": "Maintainer"
},
{
"name": "Raúl Araya",
"email": "nubeiro@gmail.com",
"role": "Maintainer"
}
],
"description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.",
"homepage": "https://github.com/php-amqplib/php-amqplib/",
"keywords": [
"message",
"queue",
"rabbitmq"
],
"time": "2018-02-11T19:28:00+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "1.0.1",
"source": {
......
......@@ -62,6 +62,10 @@ $api->version('v1', ['namespace' => 'App\Http\Controllers\v1', 'prefix' => 'api/
$api->post('token/confirm', 'TokenController@check');
$api->get('person/battery', 'user\ProfileController@battery');
$api->get('person/wallet', 'user\ProfileController@wallet');
$api->get('person/coupon', 'user\ProfileController@coupon');
});
......
......@@ -12,4 +12,77 @@ namespace Src;
class Battery
{
private $code = '';
private $power = 0;
private $batteryType = '';
private $borrowDate = '';
/**
* @return string
*/
public function getCode()
{
return $this->code;
}
/**
* @param string $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* @return int
*/
public function getPower()
{
return $this->power;
}
/**
* @param int $power
*/
public function setPower($power)
{
$this->power = $power;
}
/**
* @return string
*/
public function getBatteryType()
{
return $this->batteryType;
}
/**
* @param string $batteryType
*/
public function setBatteryType($batteryType)
{
$this->batteryType = $batteryType;
}
/**
* @return string
*/
public function getBorrowDate(): string
{
return $this->borrowDate;
}
/**
* @param string $borrowDate
*/
public function setBorrowDate(string $borrowDate): void
{
$this->borrowDate = $borrowDate;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/11
* Time: 下午11:00
*/
namespace Src;
class User
{
private $ticket = '';
private $card = 0;
private $balance = 0;
private $id = 0;
public function hasCard()
{
}
public function getAllTicket()
{
}
}
\ No newline at end of file
......@@ -39,7 +39,7 @@ class Box
public static function getOpenDoorTopic(string $boxCode)
{
return env('MQTT_PRODUCT_KEY') . '/' . $boxCode . '/open_door';
return env('MQTT_PRODUCT_KEY') . '/' . $boxCode . '/hdg_get';
}
......
......@@ -62,6 +62,7 @@ class Door
* 3:预约
* 4: 关门无电池
* 5: 开门无电池
* 6: 关门有电池
*/
private $state = 0;
......
......@@ -9,6 +9,7 @@
namespace Src\box\door;
use Log;
use DB;
trait SearchByState
......@@ -24,13 +25,10 @@ trait SearchByState
public function searchByState(string $boxCode, int $state): int
{
$redis = app('Redis');
if ($redis instanceof \Redis) {
$freeDoorIds = $redis->zRangeByScore(Door::getBoxDoorStateKey($boxCode), $state, $state);
foreach ($freeDoorIds as $id) {
$boxNumNameId = explode(',', $id);
Log::debug($boxNumNameId);
$boxId = $boxNumNameId[2];
if (Door::checkAndOccupy($boxId) === true) { //检查舱门是否被其他进程占用
return (int)$boxId;
......@@ -44,4 +42,16 @@ trait SearchByState
}
public function searchFreeRoom(string $boxCode)
{
return DB::table('box_rooms')->where([
['box_code', $boxCode],
['reserve_status', 1],
['battery_code', null],
])->first(['id']);
}
}
\ No newline at end of file
......@@ -39,6 +39,12 @@ class OrderCache
return config('redis_key.ORDER_CACHE') . ':' . $this->order->getOutTradeNo();
}
public function update(array $attribute)
{
$this->redis->hMset($this->getRedisKey(), $attribute);
return $this;
}
public function saveStartOpenReturnDoorTime()
{
$this->redis->hSet($this->getRedisKey(), 'startOpenReturnDoorTime', $this->startOpenReturnDoorTime);
......
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/11
* Time: 下午11:05
*/
namespace Src\pay_rule;
use DB;
use Log;
class CashPay extends Rule
{
private $startTime = '';
/**
* @return int
*/
public function getPayAmount(): int
{
$this->startTime = $this->orderModel->out_date;
$today = time();
$startTime = strtotime($this->startTime);
$rentTime = $today - $startTime;
$rentDay = ceil($rentTime / (60 * 60));
$system = DB::table('system')->where('id', 1)->first(['free_day', 'day_money']);
if (blank($system) === true) {
abort(500, 'system config wrong');
Log::error('system config wrong');
}
$system = $system->toArray();
$this->freeDay = $system['free_day'];
$price = $system['day_money'];
if (($rentDay % 24) > 5) {
$rentDay = (int)($rentDay / 24) + 1;
} else {
$rentDay = (int)($rentDay / 24);
}
$payDay = ($rentDay - $this->freeDay) > 0 ? ($rentDay - $this->freeDay) : 0;
//todo 检查优惠券
return $price * $payDay;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/11
* Time: 下午11:03
*/
namespace Src\pay_rule;
use App\model\OrderModel;
abstract class Rule
{
/**
* @var OrderModel
*/
protected $orderModel;
protected $freeDay = 0;
/**
* @return int
*/
public function getFreeDay(): int
{
return $this->freeDay;
}
/**
* @param int $freeDay
*/
public function setFreeDay(int $freeDay): void
{
$this->freeDay = $freeDay;
}
/**
* @param OrderModel $orderModel
*/
public function setOrderModel(OrderModel $orderModel): void
{
$this->orderModel = $orderModel;
}
public function getOrderModel(): OrderModel
{
$this->orderModel;
}
abstract public function getPayAmount(): int;
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/24
* Time: 上午11:29
*/
namespace Src\wallet;
use Auth;
class Balance
{
public static function authGet()
{
$userModel = Auth::user();
return $userModel->money;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/24
* Time: 上午11:31
*/
namespace Src\wallet;
use Auth;
class Card
{
public static function authGet()
{
$userModel = Auth::user();
return [
'card_name' => $userModel->card_name,
'begin_date' => $userModel->begin_date,
'end_date' => $userModel->end_date,
];
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/24
* Time: 上午11:29
*/
namespace Src\wallet;
use Auth;
use Tymon\JWTAuth\Http\Parser\AuthHeaders;
use DB;
class Coupon
{
public static function authGet()
{
$userModel = Auth::user();
$userId = $userModel->id;
$coupon = DB::table('tickets')->where('guest_id', $userId)->get([
'begin_date',
'end_date',
'discount',
])->toArray();
return $coupon;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/24
* Time: 上午11:29
*/
namespace Src\wallet;
use Auth;
class Deposit
{
public static function authGet()
{
$userModel = Auth::user();
return $userModel->deposit;
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: banice
* Date: 2018/10/24
* Time: 下午2:01
*/
namespace Src\wallet;
class Wallet
{
private $card;
private $balance;
private $deposit;
public function getAuthCard()
{
return Card::authGet();
}
public function getAuthBalance()
{
return Balance::authGet();
}
public function getAuthDeposit()
{
return Deposit::authGet();
}
/**
* @param mixed $card
*/
public function setCard($card): void
{
$this->card = $card;
}
/**
* @param mixed $balance
*/
public function setBalance($balance): void
{
$this->balance = $balance;
}
/**
* @param mixed $deposit
*/
public function setDeposit($deposit): void
{
$this->deposit = $deposit;
}
/**
* @return mixed
*/
public function getCard()
{
return $this->card;
}
/**
* @return mixed
*/
public function getBalance()
{
return $this->balance;
}
/**
* @return mixed
*/
public function getDeposit()
{
return $this->deposit;
}
}
\ No newline at end of file
/.idea
/vendor
composer.lock
\ No newline at end of file
language: php
php:
- 7.0
- 7.1
before_script:
- composer self-update
- composer install --prefer-source --no-interaction --dev
# script: build.sh
# script: phpunit --configuration phpunit.xml --coverage-text
The MIT License (MIT)
Copyright (c) 2015 Björn Schmitt
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# bschmitt/laravel-amqp
AMQP wrapper for Laravel and Lumen to publish and consume messages especially from RabbitMQ
[![Build Status](https://travis-ci.org/bschmitt/laravel-amqp.svg?branch=master)](https://travis-ci.org/bschmitt/laravel-amqp)
[![Latest Stable Version](https://poser.pugx.org/bschmitt/laravel-amqp/v/stable.svg)](https://packagist.org/packages/bschmitt/laravel-amqp)
[![License](https://poser.pugx.org/bschmitt/laravel-amqp/license.svg)](https://packagist.org/packages/bschmitt/laravel-amqp)
## Features
- Advanced queue configuration
- Add message to queues easily
- Listen queues with useful options
## Installation
### Composer
Add the following to your require part within the composer.json:
```js
"bschmitt/laravel-amqp": "2.*" (Laravel >= 5.5)
"bschmitt/laravel-amqp": "1.*" (Laravel < 5.5)
```
```batch
$ php composer update
```
or
```
$ php composer require bschmitt/laravel-amqp
```
## Integration
### Lumen
Create a **config** folder in the root directory of your Lumen application and copy the content
from **vendor/bschmitt/laravel-amqp/config/amqp.php** to **config/amqp.php**.
Adjust the properties to your needs.
```php
return [
'use' => 'production',
'properties' => [
'production' => [
'host' => 'localhost',
'port' => 5672,
'username' => 'username',
'password' => 'password',
'vhost' => '/',
'exchange' => 'amq.topic',
'exchange_type' => 'topic',
'consumer_tag' => 'consumer',
'ssl_options' => [], // See https://secure.php.net/manual/en/context.ssl.php
'connect_options' => [], // See https://github.com/php-amqplib/php-amqplib/blob/master/PhpAmqpLib/Connection/AMQPSSLConnection.php
'queue_properties' => ['x-ha-policy' => ['S', 'all']],
'exchange_properties' => [],
'timeout' => 0
],
],
];
```
Register the Lumen Service Provider in **bootstrap/app.php**:
```php
/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
*/
//...
$app->configure('amqp');
$app->register(Bschmitt\Amqp\LumenServiceProvider::class);
//...
```
Add Facade Support for Lumen 5.2+
```php
//...
$app->withFacades();
class_alias(\Illuminate\Support\Facades\App::class, 'App');
//...
```
### Laravel
Open **config/app.php** and add the service provider and alias:
```php
'Bschmitt\Amqp\AmqpServiceProvider',
```
```php
'Amqp' => 'Bschmitt\Amqp\Facades\Amqp',
```
## Publishing a message
### Push message with routing key
```php
Amqp::publish('routing-key', 'message');
```
### Push message with routing key and create queue
```php
Amqp::publish('routing-key', 'message' , ['queue' => 'queue-name']);
```
### Push message with routing key and overwrite properties
```php
Amqp::publish('routing-key', 'message' , ['exchange' => 'amq.direct']);
```
## Consuming messages
### Consume messages, acknowledge and stop when no message is left
```php
Amqp::consume('queue-name', function ($message, $resolver) {
var_dump($message->body);
$resolver->acknowledge($message);
$resolver->stopWhenProcessed();
});
```
### Consume messages forever
```php
Amqp::consume('queue-name', function ($message, $resolver) {
var_dump($message->body);
$resolver->acknowledge($message);
});
```
### Consume messages, with custom settings
```php
Amqp::consume('queue-name', function ($message, $resolver) {
var_dump($message->body);
$resolver->acknowledge($message);
}, [
'timeout' => 2,
'vhost' => 'vhost3'
]);
```
## Fanout example
### Publishing a message
```php
\Amqp::publish('', 'message' , [
'exchange_type' => 'fanout',
'exchange' => 'amq.fanout',
]);
```
### Consuming messages
```php
\Amqp::consume('', function ($message, $resolver) {
var_dump($message->body);
$resolver->acknowledge($message);
}, [
'exchange' => 'amq.fanout',
'exchange_type' => 'fanout',
'queue_force_declare' => true,
'queue_exclusive' => true,
'persistent' => true// required if you want to listen forever
]);
```
## Credits
* Some concepts were used from https://github.com/mookofe/tail
## License
This package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
{
"name": "bschmitt/laravel-amqp",
"description": "AMQP wrapper for Laravel and Lumen to publish and consume messages",
"keywords": [
"laravel",
"lumen",
"laravel5",
"rabbitmq",
"amqp",
"queue",
"package",
"message queue",
"Björn Schmitt",
"bschmitt"
],
"license": "MIT",
"support": {
"issues": "https://github.com/bschmitt/laravel-amqp/issues",
"source": "https://github.com/bschmitt/laravel-amqp"
},
"authors": [
{
"name": "Björn Schmitt",
"email": "code@bjoern.io"
}
],
"require": {
"php": ">=7.0",
"php-amqplib/php-amqplib": "2.*",
"illuminate/support": ">=v5.5.28"
},
"require-dev": {
"phpunit/phpunit": "~4.0",
"mockery/mockery": "~0.9",
"squizlabs/php_codesniffer": "^3.0@dev"
},
"autoload": {
"psr-4": {
"Bschmitt\\Amqp\\": "src/",
"Bschmitt\\Amqp\\Test\\": "test/"
}
},
"extra": {
"laravel": {
"providers": [
"Bschmitt\\Amqp\\AmqpServiceProvider"
],
"aliases": {
"Amqp": "Bschmitt\\Amqp\\Facades\\Amqp"
}
}
},
"minimum-stability": "dev"
}
<?php
return [
/*
|--------------------------------------------------------------------------
| Define which configuration should be used
|--------------------------------------------------------------------------
*/
'use' => 'production',
/*
|--------------------------------------------------------------------------
| AMQP properties separated by key
|--------------------------------------------------------------------------
*/
'properties' => [
'production' => [
'host' => 'rabbitmq.default.svc.cluster.local',
'port' => 5672,
'username' => 'rabbitmq',
'password' => 'senthink123!',
'vhost' => 'hdg',
'connect_options' => [],
'ssl_options' => [],
'exchange' => 'amq.topic',
'exchange_type' => 'topic',
'exchange_passive' => false,
'exchange_durable' => true,
'exchange_auto_delete' => false,
'exchange_internal' => false,
'exchange_nowait' => false,
'exchange_properties' => [],
'queue_force_declare' => false,
'queue_passive' => false,
'queue_durable' => true,
'queue_exclusive' => false,
'queue_auto_delete' => false,
'queue_nowait' => false,
'queue_properties' => ['x-ha-policy' => ['S', 'all']],
'consumer_tag' => '',
'consumer_no_local' => false,
'consumer_no_ack' => false,
'consumer_exclusive' => false,
'consumer_nowait' => false,
'timeout' => 0,
'persistent' => false,
],
],
];
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Package Test Suite">
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
</phpunit>
\ No newline at end of file
<?php
namespace Bschmitt\Amqp;
use Closure;
use Bschmitt\Amqp\Request;
use Bschmitt\Amqp\Message;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Amqp
{
/**
* @param string $routing
* @param mixed $message
* @param array $properties
*/
public function publish($routing, $message, array $properties = [])
{
$properties['routing'] = $routing;
/* @var Publisher $publisher */
$publisher = app()->make('Bschmitt\Amqp\Publisher');
$publisher
->mergeProperties($properties)
->setup();
if (is_string($message)) {
$message = new Message($message, ['content_type' => 'text/plain', 'delivery_mode' => 2]);
}
$publisher->publish($routing, $message);
Request::shutdown($publisher->getChannel(), $publisher->getConnection());
}
/**
* @param string $queue
* @param Closure $callback
* @param array $properties
* @throws Exception\Configuration
*/
public function consume($queue, Closure $callback, $properties = [])
{
$properties['queue'] = $queue;
/* @var Consumer $consumer */
$consumer = app()->make('Bschmitt\Amqp\Consumer');
$consumer
->mergeProperties($properties)
->setup();
$consumer->consume($queue, $callback);
Request::shutdown($consumer->getChannel(), $consumer->getConnection());
}
/**
* @param string $body
* @param array $properties
* @return \Bschmitt\Amqp\Message
*/
public function message($body, $properties = [])
{
return new Message($body, $properties);
}
}
<?php
namespace Bschmitt\Amqp;
use Bschmitt\Amqp\Consumer;
use Bschmitt\Amqp\Publisher;
use Illuminate\Support\ServiceProvider;
class AmqpServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = true;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->app->bind('Amqp', 'Bschmitt\Amqp\Amqp');
if (!class_exists('Amqp')) {
class_alias('Bschmitt\Amqp\Facades\Amqp', 'Amqp');
}
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
$this->app->singleton('Bschmitt\Amqp\Publisher', function ($app) {
return new Publisher(config());
});
$this->app->singleton('Bschmitt\Amqp\Consumer', function ($app) {
return new Consumer(config());
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return ['Amqp', 'Bschmitt\Amqp\Publisher', 'Bschmitt\Amqp\Consumer'];
}
}
<?php
namespace Bschmitt\Amqp;
use Illuminate\Config\Repository;
use Closure;
use PhpAmqpLib\Exception\AMQPTimeoutException;
use PhpAmqpLib\Message\AMQPMessage;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Consumer extends Request
{
/**
* @var int
*/
protected $messageCount = 0;
/**
* @param string $queue
* @param Closure $closure
* @return bool
* @throws \Exception
*/
public function consume($queue, Closure $closure)
{
try {
$this->messageCount = $this->getQueueMessageCount();
if (!$this->getProperty('persistent') && $this->messageCount == 0) {
throw new Exception\Stop();
}
/*
queue: Queue from where to get the messages
consumer_tag: Consumer identifier
no_local: Don't receive messages published by this consumer.
no_ack: Tells the server if the consumer will acknowledge the messages.
exclusive: Request exclusive consumer access, meaning only this consumer can access the queue
nowait:
callback: A PHP Callback
*/
$object = $this;
$this->getChannel()->basic_consume(
$queue,
$this->getProperty('consumer_tag'),
$this->getProperty('consumer_no_local'),
$this->getProperty('consumer_no_ack'),
$this->getProperty('consumer_exclusive'),
$this->getProperty('consumer_nowait'),
function ($message) use ($closure, $object) {
$closure($message, $object);
}
);
// consume
while (count($this->getChannel()->callbacks)) {
$this->getChannel()->wait(
null,
!$this->getProperty('blocking'),
$this->getProperty('timeout') ? $this->getProperty('timeout') : 0
);
}
} catch (\Exception $e) {
if ($e instanceof Exception\Stop) {
return true;
}
if ($e instanceof AMQPTimeoutException) {
return true;
}
throw $e;
}
return true;
}
/**
* Acknowledges a message
*
* @param AMQPMessage $message
*/
public function acknowledge(AMQPMessage $message)
{
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
if ($message->body === 'quit') {
$message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
}
}
/**
* Rejects a message and requeues it if wanted (default: false)
*
* @param AMQPMessage $message
* @param bool $requeue
*/
public function reject(AMQPMessage $message, $requeue = false)
{
$message->delivery_info['channel']->basic_reject($message->delivery_info['delivery_tag'], $requeue);
}
/**
* Stops consumer when no message is left
*
* @throws Exception\Stop
*/
public function stopWhenProcessed()
{
if (--$this->messageCount <= 0) {
throw new Exception\Stop();
}
}
}
<?php
namespace Bschmitt\Amqp;
use Illuminate\Config\Repository;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
abstract class Context
{
const REPOSITORY_KEY = 'amqp';
/**
* @var array
*/
protected $properties = [];
/**
* Context constructor.
*
* @param Repository $config
*/
public function __construct(Repository $config)
{
$this->extractProperties($config);
}
/**
* @param Repository $config
*/
protected function extractProperties(Repository $config)
{
if ($config->has(self::REPOSITORY_KEY)) {
$data = $config->get(self::REPOSITORY_KEY);
$this->properties = $data['properties'][$data['use']];
}
}
/**
* @param array $properties
* @return $this
*/
public function mergeProperties(array $properties)
{
$this->properties = array_merge($this->properties, $properties);
return $this;
}
/**
* @return array
*/
public function getProperties()
{
return $this->properties;
}
/**
* @param string $key
* @return mixed
*/
public function getProperty($key)
{
return array_key_exists($key, $this->properties) ? $this->properties[$key] : null;
}
/**
* @return mixed
*/
abstract public function setup();
}
<?php
namespace Bschmitt\Amqp\Exception;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Configuration extends \Exception
{
}
<?php
namespace Bschmitt\Amqp\Exception;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Stop extends \Exception
{
}
<?php
namespace Bschmitt\Amqp\Facades;
use Illuminate\Support\Facades\Facade;
/**
* @author Björn Schmitt <code@bjoern.io>
* @see Bschmitt\Amqp\Amqp
*/
class Amqp extends Facade
{
/**
* @return string
*/
protected static function getFacadeAccessor()
{
return 'Amqp';
}
}
<?php
namespace Bschmitt\Amqp;
use Illuminate\Support\ServiceProvider;
/**
* Lumen Service Provider
*
* @author Björn Schmitt <code@bjoern.io>
*/
class LumenServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
}
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
$this->app->bind('Bschmitt\Amqp\Publisher', function ($app) {
return new Publisher($app->config);
});
$this->app->bind('Bschmitt\Amqp\Consumer', function ($app) {
return new Consumer($app->config);
});
$this->app->bind('Amqp', 'Bschmitt\Amqp\Amqp');
if (!class_exists('Amqp')) {
class_alias('Bschmitt\Amqp\Facades\Amqp', 'Amqp');
}
}
}
<?php
namespace Bschmitt\Amqp;
use PhpAmqpLib\Message\AMQPMessage;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Message extends AMQPMessage
{
}
<?php
namespace Bschmitt\Amqp;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Publisher extends Request
{
/**
* @param string $routing
* @param Message $message
* @throws Exception\Configuration
*/
public function publish($routing, $message)
{
$this->getChannel()->basic_publish($message, $this->getProperty('exchange'), $routing);
}
}
<?php
namespace Bschmitt\Amqp;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Connection\AMQPSSLConnection;
use PhpAmqpLib\Channel\AMQPChannel;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class Request extends Context
{
/**
* @var AMQPStreamConnection
*/
protected $connection;
/**
* @var AMQPChannel
*/
protected $channel;
/**
* @var array
*/
protected $queueInfo;
/**
*
*/
public function connect()
{
$this->connection = new AMQPSSLConnection(
$this->getProperty('host'),
$this->getProperty('port'),
$this->getProperty('username'),
$this->getProperty('password'),
$this->getProperty('vhost'),
$this->getProperty('ssl_options'),
$this->getProperty('connect_options')
);
$this->channel = $this->connection->channel();
}
/**
* @throws Exception\Configuration
*/
public function setup()
{
$this->connect();
$exchange = $this->getProperty('exchange');
if (empty($exchange)) {
throw new Exception\Configuration('Please check your settings, exchange is not defined.');
}
/*
name: $exchange
type: topic
passive: false
durable: true // the exchange will survive server restarts
auto_delete: false //the exchange won't be deleted once the channel is closed.
*/
$this->channel->exchange_declare(
$exchange,
$this->getProperty('exchange_type'),
$this->getProperty('exchange_passive'),
$this->getProperty('exchange_durable'),
$this->getProperty('exchange_auto_delete'),
$this->getProperty('exchange_internal'),
$this->getProperty('exchange_nowait'),
$this->getProperty('exchange_properties')
);
$queue = $this->getProperty('queue');
if (!empty($queue) || $this->getProperty('queue_force_declare')) {
/*
name: $queue
passive: false
durable: true // the queue will survive server restarts
exclusive: false // queue is deleted when connection closes
auto_delete: false //the queue won't be deleted once the channel is closed.
nowait: false // Doesn't wait on replies for certain things.
parameters: array // Extra data, like high availability params
*/
/** @var ['queue name', 'message count',] queueInfo */
$this->queueInfo = $this->channel->queue_declare(
$queue,
$this->getProperty('queue_passive'),
$this->getProperty('queue_durable'),
$this->getProperty('queue_exclusive'),
$this->getProperty('queue_auto_delete'),
$this->getProperty('queue_nowait'),
$this->getProperty('queue_properties')
);
$this->channel->queue_bind(
$queue ?: $this->queueInfo[0],
$exchange,
$this->getProperty('routing')
);
}
// clear at shutdown
$this->connection->set_close_on_destruct(true);
}
/**
* @return \PhpAmqpLib\Channel\AMQPChannel
*/
public function getChannel()
{
return $this->channel;
}
/**
* @return AMQPStreamConnection
*/
public function getConnection()
{
return $this->connection;
}
/**
* @return int
*/
public function getQueueMessageCount()
{
if (is_array($this->queueInfo)) {
return $this->queueInfo[1];
}
return 0;
}
/**
* @param AMQPChannel $channel
* @param AMQPStreamConnection $connection
*/
public static function shutdown(AMQPChannel $channel, AMQPStreamConnection $connection)
{
$channel->close();
$connection->close();
}
}
<?php
namespace Bschmitt\Amqp\Test;
use \Mockery;
use Illuminate\Config\Repository;
class BaseTestCase extends \PHPUnit_Framework_TestCase
{
const REPOSITORY_KEY = 'amqp';
protected $configRepository;
protected $defaultConfig;
protected function setUp()
{
$amqpConfig = include dirname(__FILE__).'/../config/amqp.php';
$this->defaultConfig = $amqpConfig['properties'][$amqpConfig['use']];
$config = Mockery::mock('\Illuminate\Config\Repository');
$config->shouldReceive('has')->with(self::REPOSITORY_KEY)->andReturn(true);
$config->shouldReceive('get')->with(self::REPOSITORY_KEY)->andReturn($amqpConfig);
$this->configRepository = $config;
}
protected function tearDown()
{
// necessary for Mockery to check if methods were called and with what arguments
Mockery::close();
}
protected function setProtectedProperty($class, $mock, $propertyName, $value)
{
$reflectionClass = new \ReflectionClass($class);
$channelProperty = $reflectionClass->getProperty($propertyName);
$channelProperty->setAccessible(true);
$channelProperty->setValue($mock, $value);
$channelProperty->setAccessible(false);
}
}
<?php
namespace Bschmitt\Amqp\Test;
use \Mockery;
use Bschmitt\Amqp\Publisher;
use Illuminate\Config\Repository;
/**
* @author Björn Schmitt <code@bjoern.io>
*/
class PublisherTest extends BaseTestCase
{
private $publisherMock;
private $connectionMock;
private $channelMock;
protected function setUp()
{
parent::setUp();
// partial mock of \Bschmitt\Amqp\Publisher
// we want all methods except [connect] to be real
$this->publisherMock = Mockery::mock('\Bschmitt\Amqp\Publisher[connect]', [$this->configRepository]);
// set connection and channel properties
$this->channelMock = Mockery::mock('\PhpAmqpLib\Channel\AMQPChannel');
$this->connectionMock = Mockery::mock('\PhpAmqpLib\Connection\AMQPSSLConnection');
// channel and connection are both protected and without changing the source this was the only way to mock them
$this->setProtectedProperty('\Bschmitt\Amqp\Publisher', $this->publisherMock, 'channel', $this->channelMock);
$this->setProtectedProperty('\Bschmitt\Amqp\Publisher', $this->publisherMock, 'connection', $this->connectionMock);
}
public function testSetupPublisher()
{
$this->connectionMock->shouldReceive('set_close_on_destruct')->with(true)->times(1);
$this->channelMock->shouldReceive('exchange_declare')->with(
$this->defaultConfig['exchange'],
$this->defaultConfig['exchange_type'],
$this->defaultConfig['exchange_passive'],
$this->defaultConfig['exchange_durable'],
$this->defaultConfig['exchange_auto_delete'],
$this->defaultConfig['exchange_internal'],
$this->defaultConfig['exchange_nowait'],
$this->defaultConfig['exchange_properties']
)->times(1);
$this->publisherMock->shouldReceive('connect')->times(1);
$this->publisherMock->setup();
}
public function testPublishShouldAChannelMethodWithProperParams()
{
$routing = 'routing-key';
$message = 'sample-message';
$this->channelMock->shouldReceive('basic_publish')
->with(
$message,
$this->defaultConfig['exchange'],
$routing
)->times(1);
$this->publisherMock->publish($routing, $message);
}
public function testPublishShouldCallAChannelMethodWithCustomExchangeValue()
{
$routing = 'routing-key';
$message = 'sample-message';
$exchange = 'custom-exchange';
$this->publisherMock->mergeProperties(['exchange' => $exchange]);
$this->channelMock->shouldReceive('basic_publish')
->with(
$message,
$exchange,
$routing
)->times(1);
$this->publisherMock->publish($routing, $message);
}
}
<?php
namespace Bschmitt\Amqp\Test;
use \Mockery;
use Bschmitt\Amqp\Request;
use Bschmitt\Amqp\Context;
class RequestTest extends BaseTestCase
{
private $connectionMock;
private $channelMock;
private $requestMock;
protected function setUp()
{
parent::setUp();
$this->channelMock = Mockery::mock('\PhpAmqpLib\Channel\AMQPChannel');
$this->connectionMock = Mockery::mock('\PhpAmqpLib\Connection\AMQPSSLConnection');
// partial mock of \Bschmitt\Amqp\Publisher
// we want all methods except [connect,getChannel] to be real
$this->requestMock = Mockery::mock('\Bschmitt\Amqp\Request[connect,getChannel]', [$this->configRepository]);
// channel and connection are both protected and without changing the source this was the only way to mock them
$this->setProtectedProperty('\Bschmitt\Amqp\Request', $this->requestMock, 'channel', $this->channelMock);
$this->setProtectedProperty('\Bschmitt\Amqp\Request', $this->requestMock, 'connection', $this->connectionMock);
}
/**
* @expectedException Bschmitt\Amqp\Exception\Configuration
*/
public function testIfEmptyExchangeThrowsAnException()
{
$this->requestMock->mergeProperties(['exchange' => '']);
$this->requestMock->shouldReceive('connect');
$this->requestMock->setup();
}
public function testIfQueueGetsDeclaredAndBoundIfInConfig()
{
$queueName = 'amqp-test';
$routing = 'routing-test';
$this->requestMock->mergeProperties([
'queue' => $queueName,
'queue_force_declare' => true,
'routing' => $routing
]);
$this->channelMock->shouldReceive('exchange_declare');
$this->requestMock->shouldReceive('connect');
$this->channelMock->shouldReceive('queue_declare')
->with(
$queueName,
$this->defaultConfig['queue_passive'],
$this->defaultConfig['queue_durable'],
$this->defaultConfig['queue_exclusive'],
$this->defaultConfig['queue_auto_delete'],
$this->defaultConfig['queue_nowait'],
$this->defaultConfig['queue_properties']
)
->andReturn([$queueName, 4])
->times(1);
$this->channelMock->shouldReceive('queue_bind')
->with(
$queueName,
$this->defaultConfig['exchange'],
$routing
)
->times(1);
$this->connectionMock->shouldReceive('set_close_on_destruct')->with(true)->times(1);
$this->requestMock->setup();
}
public function testQueueMessageCountShouldBeZeroIfQueueinfoIsNotSet()
{
$this->assertEquals($this->requestMock->getQueueMessageCount(), 0);
}
public function testQueueMessageCountShouldReturnMessageCount()
{
$messageCount = 4;
$queueInfo = ['queue-name', $messageCount];
$this->setProtectedProperty('\Bschmitt\Amqp\Request', $this->requestMock, 'queueInfo', $queueInfo);
$this->assertEquals($this->requestMock->getQueueMessageCount(), $messageCount);
}
public function testIfChannelAndConnectionAreClosedWhenShutdownIsInvoked()
{
$this->channelMock->shouldReceive('close')->times(1);
$this->connectionMock->shouldReceive('close')->times(1);
$this->requestMock::shutDown($this->channelMock, $this->connectionMock);
}
}
......@@ -31,6 +31,7 @@ return array(
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'PhpAmqpLib\\' => array($vendorDir . '/php-amqplib/php-amqplib/PhpAmqpLib'),
'Overtrue\\LaravelLang\\' => array($vendorDir . '/overtrue/laravel-lang/src'),
'Namshi\\JOSE\\' => array($vendorDir . '/namshi/jose/src/Namshi/JOSE'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
......@@ -82,6 +83,8 @@ return array(
'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
'Composer\\' => array($vendorDir . '/composer/composer/src/Composer'),
'Bschmitt\\Amqp\\Test\\' => array($vendorDir . '/bschmitt/laravel-amqp/test'),
'Bschmitt\\Amqp\\' => array($vendorDir . '/bschmitt/laravel-amqp/src'),
'Barryvdh\\LaravelIdeHelper\\' => array($vendorDir . '/barryvdh/laravel-ide-helper/src'),
'App\\' => array($baseDir . '/app'),
'' => array($vendorDir . '/nesbot/carbon/src'),
......
......@@ -62,6 +62,7 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
'Psr\\Log\\' => 8,
'Psr\\Http\\Message\\' => 17,
'Psr\\Container\\' => 14,
'PhpAmqpLib\\' => 11,
),
'O' =>
array (
......@@ -146,6 +147,8 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
),
'B' =>
array (
'Bschmitt\\Amqp\\Test\\' => 19,
'Bschmitt\\Amqp\\' => 14,
'Barryvdh\\LaravelIdeHelper\\' => 26,
),
'A' =>
......@@ -257,6 +260,10 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
array (
0 => __DIR__ . '/..' . '/psr/container/src',
),
'PhpAmqpLib\\' =>
array (
0 => __DIR__ . '/..' . '/php-amqplib/php-amqplib/PhpAmqpLib',
),
'Overtrue\\LaravelLang\\' =>
array (
0 => __DIR__ . '/..' . '/overtrue/laravel-lang/src',
......@@ -461,6 +468,14 @@ class ComposerStaticInit218e52271e7414c2c8c975db4e4d2459
array (
0 => __DIR__ . '/..' . '/composer/composer/src/Composer',
),
'Bschmitt\\Amqp\\Test\\' =>
array (
0 => __DIR__ . '/..' . '/bschmitt/laravel-amqp/test',
),
'Bschmitt\\Amqp\\' =>
array (
0 => __DIR__ . '/..' . '/bschmitt/laravel-amqp/src',
),
'Barryvdh\\LaravelIdeHelper\\' =>
array (
0 => __DIR__ . '/..' . '/barryvdh/laravel-ide-helper/src',
......
......@@ -127,6 +127,74 @@
]
},
{
"name": "bschmitt/laravel-amqp",
"version": "2.0.3",
"version_normalized": "2.0.3.0",
"source": {
"type": "git",
"url": "https://github.com/bschmitt/laravel-amqp.git",
"reference": "e9f83dfcd5feb1fda5648087985c8e62456acd85"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bschmitt/laravel-amqp/zipball/e9f83dfcd5feb1fda5648087985c8e62456acd85",
"reference": "e9f83dfcd5feb1fda5648087985c8e62456acd85",
"shasum": ""
},
"require": {
"illuminate/support": ">=v5.5.28",
"php": ">=7.0",
"php-amqplib/php-amqplib": "2.*"
},
"require-dev": {
"mockery/mockery": "~0.9",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "^3.0@dev"
},
"time": "2018-07-13T10:38:45+00:00",
"type": "library",
"extra": {
"laravel": {
"providers": [
"Bschmitt\\Amqp\\AmqpServiceProvider"
],
"aliases": {
"Amqp": "Bschmitt\\Amqp\\Facades\\Amqp"
}
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Bschmitt\\Amqp\\": "src/",
"Bschmitt\\Amqp\\Test\\": "test/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Björn Schmitt",
"email": "code@bjoern.io"
}
],
"description": "AMQP wrapper for Laravel and Lumen to publish and consume messages",
"keywords": [
"AMQP",
"Björn Schmitt",
"bschmitt",
"laravel",
"laravel5",
"lumen",
"message queue",
"package",
"queue",
"rabbitmq"
]
},
{
"name": "caouecs/laravel-lang",
"version": "3.0.54",
"version_normalized": "3.0.54.0",
......@@ -3271,6 +3339,79 @@
"description": "Library for handling version information and constraints"
},
{
"name": "php-amqplib/php-amqplib",
"version": "v2.7.2",
"version_normalized": "2.7.2.0",
"source": {
"type": "git",
"url": "https://github.com/php-amqplib/php-amqplib.git",
"reference": "dfd3694a86f1a7394d3693485259d4074a6ec79b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/dfd3694a86f1a7394d3693485259d4074a6ec79b",
"reference": "dfd3694a86f1a7394d3693485259d4074a6ec79b",
"shasum": ""
},
"require": {
"ext-bcmath": "*",
"ext-mbstring": "*",
"php": ">=5.3.0"
},
"replace": {
"videlalvaro/php-amqplib": "self.version"
},
"require-dev": {
"phpdocumentor/phpdocumentor": "^2.9",
"phpunit/phpunit": "^4.8",
"scrutinizer/ocular": "^1.1",
"squizlabs/php_codesniffer": "^2.5"
},
"suggest": {
"ext-sockets": "Use AMQPSocketConnection"
},
"time": "2018-02-11T19:28:00+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.7-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"PhpAmqpLib\\": "PhpAmqpLib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Alvaro Videla",
"role": "Original Maintainer"
},
{
"name": "John Kelly",
"email": "johnmkelly86@gmail.com",
"role": "Maintainer"
},
{
"name": "Raúl Araya",
"email": "nubeiro@gmail.com",
"role": "Maintainer"
}
],
"description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.",
"homepage": "https://github.com/php-amqplib/php-amqplib/",
"keywords": [
"message",
"queue",
"rabbitmq"
]
},
{
"name": "phpdocumentor/reflection-common",
"version": "1.0.1",
"version_normalized": "1.0.1.0",
......
[submodule "docs"]
path = docs
url = https://github.com/php-amqplib/php-amqplib.git
branch = gh-pages
# Changelog
All Notable changes to `php-amqplib` will be documented in this file
## 2.7.2 - 2018-02-11
[GitHub Milestone](https://github.com/php-amqplib/php-amqplib/milestone/5)
- PHP `5.3` compatibility [PR](https://github.com/php-amqplib/php-amqplib/issues/539)
## 2.7.1 - 2018-02-01
- Support PHPUnit 6 [PR](https://github.com/php-amqplib/php-amqplib/pull/530)
- Use `tcp_nodelay` for `StreamIO` [PR](https://github.com/php-amqplib/php-amqplib/pull/517)
- Pass connection timeout to `wait` method [PR](https://github.com/php-amqplib/php-amqplib/pull/512)
- Fix possible indefinite waiting for data in StreamIO [PR](https://github.com/php-amqplib/php-amqplib/pull/423), [PR](https://github.com/php-amqplib/php-amqplib/pull/534)
- Change protected method check_heartbeat to public [PR](https://github.com/php-amqplib/php-amqplib/pull/520)
- Ensure access levels are consistent for calling `check_heartbeat` [PR](https://github.com/php-amqplib/php-amqplib/pull/535)
## 2.7.0 - 2017-09-20
### Added
- Increased overall test coverage
- Bring heartbeat support to socket connection
- Add message delivery tag for publisher confirms
- Add support for serializing DateTimeImmutable objects
### Fixed
- Fixed infinite loop on reconnect - check_heartbeat
- Fixed signal handling exit example
- Fixed exchange_unbind arguments
- Fixed invalid annotation for channel_id
- Fixed socket null error on php 5.3 version
- Fixed timeout parameters on HHVM before calling stream_select
### Changed
- declare(ticks=1) no longer needed after PHP5.3 / amqplib 2.4.1
- Minor DebugHelper improvements
### Enhancements
- Add extensions requirements to README.md
- Add PHP 7.1 to Travis build
- Reduce memory usage in StreamIO::write()
- Re-enable heartbeats after reconnection
## 2.6.3 - 2016-04-11
### Added
- Added the ability to set timeout as float
### Fixed
- Fixed restoring of error_handler on connection error
### Enhancements
- Verify read_write_timeout is at least 2x the heartbeat (if set)
- Many PHPDoc fixes
- Throw exception when trying to create an exchange on a closed connection
## 2.6.2 - 2016-03-02
### Added
- Added AMQPLazySocketConnection
- AbstractConnection::getServerProperties method to retrieve server properties.
- AMQPReader::wait() will throw IOWaitException on stream_select failure
- Add PHPDocs to Auto-generated Protocol Classes
### Fixed
- Disable heartbeat when closing connection
- Fix for when the default error handler is not restored in StreamIO
### Enhancements
- Cleanup tests and improve testing performance
- Confirm received valid frame type on wait_frame in AbstractConnection
- Update DEMO files closer to PSR-2 standards
## 2.6.1 - 2016-02-12
### Added
- Add constants for delivery modes to AMQPMessage
### Fixed
- Fix some PHPDoc problems
- AbstractCollection value de/encoding on PHP7
- StreamIO: fix "bad write retry" in SSL mode
### Enhancements
- Update PHPUnit configuration
- Add scrutinizer-ci configuration
- Organizational changes from videlalvaro to php-amqplib org
- Minor complexity optimizations, code organization, and code cleanup
## 2.6.0 - 2015-09-23
### BC Breaking Changes
- The `AMQPStreamConnection` class now throws `ErrorExceptions` when errors happen while reading/writing to the network.
### Added
- Heartbeat frames will decrease the timeout used when calling wait_channel - heartbeat frames do not reset the timeout
### Fixed
- Declared the class AbstractChannel as being an abstract class
- Reads, writes and signals respond immediately instead of waiting for a timeout
- Fatal error in some cases on Channel.wait with timeout when RabbitMQ restarted
- Remove warning when trying to push a deferred frame
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of
fostering an open and welcoming community, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating
documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic
addresses, without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to
fairly and consistently applying these principles to every aspect of managing
this project. Project maintainers who do not follow or enforce the Code of
Conduct may be permanently removed from the project team.
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting a project maintainer. All complaints will be reviewed
and investigated and will result in a response that is deemed necessary and
appropriate to the circumstances. Maintainers are obligated to maintain
confidentiality with regard to the reporter of an incident.
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.3.0, available at
[http://contributor-covenant.org/version/1/3/0/][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/3/0/
# Contributing
Contributions are **welcome** and will be fully **credited**.
We accept contributions via Pull Requests on [Github](https://github.com/php-amqplib/php-amqplib).
## Pull Requests
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
- **Document any change in behaviour** - Make sure the README and any other relevant documentation are kept up-to-date.
- **Consider our release cycle** - We try to follow semver. Randomly breaking public APIs is not an option.
- **Create topic branches** - Don't ask us to pull from your master branch.
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
## Running Tests
``` bash
$ phpunit
```
**Happy coding**!
Following people contributed to this project:
Barry Pederson <bp@barryp.org> - author of original Python lib
Vadim Zaliva <lord@crocodile.org> - PHP paort
taavi013@gmail.com patches - patches
Sean Murphy http://code.google.com/u/sgmurphy/ - patches
spiderbill http://code.google.com/u/spiderbill/ - patches
<?php
namespace PhpAmqpLib\Connection;
/**
* Class AMQPConnection
*
* Kept for BC
*
* @deprecated
*/
class AMQPConnection extends AMQPStreamConnection
{
}
<?php
namespace PhpAmqpLib\Connection;
class AMQPLazyConnection extends AMQPStreamConnection
{
/**
* Gets socket from current connection
*
* @deprecated
*/
public function getSocket()
{
$this->connect();
return parent::getSocket();
}
/**
* {@inheritdoc}
*/
public function channel($channel_id = null)
{
$this->connect();
return parent::channel($channel_id);
}
/**
* @return null|\PhpAmqpLib\Wire\IO\AbstractIO
*/
public function getIO()
{
if (empty($this->io)) {
$this->connect();
}
return $this->io;
}
/**
* Should the connection be attempted during construction?
*
* @return bool
*/
public function connectOnConstruct()
{
return false;
}
}
<?php
namespace PhpAmqpLib\Connection;
/**
* Yet another lazy connection. This time using sockets. Current architecture doesn't allow to wrap existing connections
*/
class AMQPLazySocketConnection extends AMQPSocketConnection
{
/**
* Gets socket from current connection
*
* @deprecated
*/
public function getSocket()
{
$this->connect();
return parent::getSocket();
}
/**
* {@inheritdoc}
*/
public function channel($channel_id = null)
{
$this->connect();
return parent::channel($channel_id);
}
/**
* @return null|\PhpAmqpLib\Wire\IO\AbstractIO
*/
public function getIO()
{
if (empty($this->io)) {
$this->connect();
}
return $this->io;
}
/**
* Should the connection be attempted during construction?
*
* @return bool
*/
public function connectOnConstruct()
{
return false;
}
}
<?php
namespace PhpAmqpLib\Connection;
class AMQPSSLConnection extends AMQPStreamConnection
{
/**
* @param string $host
* @param int $port
* @param string $user
* @param string $password
* @param string $vhost
* @param array $ssl_options
* @param array $options
*/
public function __construct(
$host,
$port,
$user,
$password,
$vhost = '/',
$ssl_options = array(),
$options = array()
) {
$ssl_context = empty($ssl_options) ? null : $this->create_ssl_context($ssl_options);
parent::__construct(
$host,
$port,
$user,
$password,
$vhost,
isset($options['insist']) ? $options['insist'] : false,
isset($options['login_method']) ? $options['login_method'] : 'AMQPLAIN',
isset($options['login_response']) ? $options['login_response'] : null,
isset($options['locale']) ? $options['locale'] : 'en_US',
isset($options['connection_timeout']) ? $options['connection_timeout'] : 3,
isset($options['read_write_timeout']) ? $options['read_write_timeout'] : 3,
$ssl_context,
isset($options['keepalive']) ? $options['keepalive'] : false,
isset($options['heartbeat']) ? $options['heartbeat'] : 0
);
}
/**
* @param array $options
* @return resource
*/
private function create_ssl_context($options)
{
$ssl_context = stream_context_create();
foreach ($options as $k => $v) {
stream_context_set_option($ssl_context, 'ssl', $k, $v);
}
return $ssl_context;
}
}
<?php
namespace PhpAmqpLib\Connection;
use PhpAmqpLib\Wire\IO\SocketIO;
class AMQPSocketConnection extends AbstractConnection
{
/**
* @param string $host
* @param int $port
* @param string $user
* @param string $password
* @param string $vhost
* @param bool $insist
* @param string $login_method
* @param null $login_response
* @param string $locale
* @param float $read_timeout
* @param bool $keepalive
* @param int $write_timeout
* @param int $heartbeat
*/
public function __construct(
$host,
$port,
$user,
$password,
$vhost = '/',
$insist = false,
$login_method = 'AMQPLAIN',
$login_response = null,
$locale = 'en_US',
$read_timeout = 3,
$keepalive = false,
$write_timeout = 3,
$heartbeat = 0
) {
$io = new SocketIO($host, $port, $read_timeout, $keepalive, $write_timeout, $heartbeat);
parent::__construct(
$user,
$password,
$vhost,
$insist,
$login_method,
$login_response,
$locale,
$io,
$heartbeat
);
}
}
<?php
namespace PhpAmqpLib\Connection;
use PhpAmqpLib\Wire\IO\StreamIO;
class AMQPStreamConnection extends AbstractConnection
{
/**
* @param string $host
* @param string $port
* @param string $user
* @param string $password
* @param string $vhost
* @param bool $insist
* @param string $login_method
* @param null $login_response
* @param string $locale
* @param float $connection_timeout
* @param float $read_write_timeout
* @param null $context
* @param bool $keepalive
* @param int $heartbeat
*/
public function __construct(
$host,
$port,
$user,
$password,
$vhost = '/',
$insist = false,
$login_method = 'AMQPLAIN',
$login_response = null,
$locale = 'en_US',
$connection_timeout = 3.0,
$read_write_timeout = 3.0,
$context = null,
$keepalive = false,
$heartbeat = 0
) {
$io = new StreamIO(
$host,
$port,
$connection_timeout,
$read_write_timeout,
$context,
$keepalive,
$heartbeat
);
parent::__construct(
$user,
$password,
$vhost,
$insist,
$login_method,
$login_response,
$locale,
$io,
$heartbeat,
$connection_timeout
);
// save the params for the use of __clone, this will overwrite the parent
$this->construct_params = func_get_args();
}
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPBasicCancelException extends \Exception implements AMQPExceptionInterface
{
/** @var string */
public $consumerTag;
/**
* @param string $consumerTag
*/
public function __construct($consumerTag)
{
$this->consumerTag = $consumerTag;
}
}
<?php
namespace PhpAmqpLib\Exception;
/**
* @deprecated use AMQPProtocolChannelException instead
*/
class AMQPChannelException extends AMQPException
{
}
<?php
namespace PhpAmqpLib\Exception;
/**
* @deprecated use AMQPProtocolConnectionException instead
*/
class AMQPConnectionException extends AMQPException
{
}
<?php
namespace PhpAmqpLib\Exception;
//TODO refactor usage of static methods
use PhpAmqpLib\Channel\AbstractChannel;
use PhpAmqpLib\Helper\MiscHelper;
/**
* @deprecated use AMQPProtocolException instead
*/
class AMQPException extends \Exception
{
/** @var string */
public $amqp_reply_code;
/** @var int */
public $amqp_reply_text;
/** @var \Exception */
public $amqp_method_sig;
/** @var array */
public $args;
/**
* @param string $reply_code
* @param int $reply_text
* @param array $method_sig
*/
public function __construct($reply_code, $reply_text, $method_sig)
{
parent::__construct($reply_text, $reply_code);
$this->amqp_reply_code = $reply_code; // redundant, but kept for BC
$this->amqp_reply_text = $reply_text; // redundant, but kept for BC
$this->amqp_method_sig = $method_sig;
$ms = MiscHelper::methodSig($method_sig);
$protocolClass = AbstractChannel::$PROTOCOL_CONSTANTS_CLASS;
$mn = isset($protocolClass::$GLOBAL_METHOD_NAMES[$ms])
? $protocolClass::$GLOBAL_METHOD_NAMES[$ms]
: $mn = '';
$this->args = array($reply_code, $reply_text, $method_sig, $mn);
}
}
<?php
namespace PhpAmqpLib\Exception;
interface AMQPExceptionInterface
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPIOException extends \Exception implements AMQPExceptionInterface
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPIOWaitException extends AMQPRuntimeException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPInvalidArgumentException extends \RuntimeException implements AMQPExceptionInterface
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPLogicException extends \LogicException implements AMQPExceptionInterface
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPOutOfBoundsException extends \OutOfBoundsException implements AMQPExceptionInterface
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPOutOfRangeException extends \OutOfRangeException implements AMQPExceptionInterface
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPProtocolChannelException extends AMQPProtocolException
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPProtocolConnectionException extends AMQPProtocolException
{
}
<?php
namespace PhpAmqpLib\Exception;
//TODO refactor usage of static methods
use PhpAmqpLib\Channel\AbstractChannel;
use PhpAmqpLib\Helper\MiscHelper;
class AMQPProtocolException extends \Exception implements AMQPExceptionInterface
{
/** @var string */
public $amqp_reply_code;
/** @var int */
public $amqp_reply_text;
/** @var \Exception */
public $amqp_method_sig;
/** @var array */
public $args;
/**
* @param string $reply_code
* @param int $reply_text
* @param array $method_sig
*/
public function __construct($reply_code, $reply_text, $method_sig)
{
parent::__construct($reply_text, $reply_code);
$this->amqp_reply_code = $reply_code; // redundant, but kept for BC
$this->amqp_reply_text = $reply_text; // redundant, but kept for BC
$this->amqp_method_sig = $method_sig;
$ms = MiscHelper::methodSig($method_sig);
$protocolClass = AbstractChannel::$PROTOCOL_CONSTANTS_CLASS;
$mn = isset($protocolClass::$GLOBAL_METHOD_NAMES[$ms])
? $protocolClass::$GLOBAL_METHOD_NAMES[$ms]
: $mn = '';
$this->args = array($reply_code, $reply_text, $method_sig, $mn);
}
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPRuntimeException extends \RuntimeException implements AMQPExceptionInterface
{
}
<?php
namespace PhpAmqpLib\Exception;
class AMQPTimeoutException extends \RuntimeException implements AMQPExceptionInterface
{
}
<?php
namespace PhpAmqpLib\Helper;
class DebugHelper
{
/**
* @var bool
*/
protected $debug;
/**
* @var resource
*/
protected $debug_output;
/**
* @var string
*/
protected $PROTOCOL_CONSTANTS_CLASS;
/**
* @param string $PROTOCOL_CONSTANTS_CLASS
*/
public function __construct($PROTOCOL_CONSTANTS_CLASS) {
if(!defined('STDOUT')) define('STDOUT', fopen('php://stdout', 'w'));
$this->debug = defined('AMQP_DEBUG') ? AMQP_DEBUG : false;
$this->debug_output = defined('AMQP_DEBUG_OUTPUT') ? AMQP_DEBUG_OUTPUT : STDOUT;
$this->PROTOCOL_CONSTANTS_CLASS = $PROTOCOL_CONSTANTS_CLASS;
}
/**
* @param string $msg
*/
public function debug_msg($msg) {
if ($this->debug) {
$this->print_msg($msg);
}
}
/**
* @param array $allowed_methods
*/
public function debug_allowed_methods($allowed_methods) {
if ($allowed_methods) {
$msg = 'waiting for ' . implode(', ', $allowed_methods);
} else {
$msg = 'waiting for any method';
}
$this->debug_msg($msg);
}
/**
* @param string $method_sig
*/
public function debug_method_signature1($method_sig) {
$this->debug_method_signature('< %s:', $method_sig);
}
/**
* @param string $msg
* @param string $method_sig
*/
public function debug_method_signature($msg, $method_sig) {
if ($this->debug) {
$protocolClass = $this->PROTOCOL_CONSTANTS_CLASS;
$this->debug_msg(sprintf(
$msg . ': %s',
MiscHelper::methodSig($method_sig),
$protocolClass::$GLOBAL_METHOD_NAMES[MiscHelper::methodSig($method_sig)]
));
}
}
/**
* @param string $data
*/
public function debug_hexdump($data) {
if ($this->debug) {
$this->debug_msg(sprintf(
'< [hex]: %s%s',
PHP_EOL,
MiscHelper::hexdump($data, $htmloutput = false, $uppercase = true, $return = true)
));
}
}
/**
* @param int $version_major
* @param int $version_minor
* @param array $server_properties
* @param array $mechanisms
* @param array $locales
*/
public function debug_connection_start($version_major, $version_minor, $server_properties, $mechanisms, $locales) {
if ($this->debug) {
$this->debug_msg(sprintf(
'Start from server, version: %d.%d, properties: %s, mechanisms: %s, locales: %s',
$version_major,
$version_minor,
MiscHelper::dump_table($server_properties),
implode(', ', $mechanisms),
implode(', ', $locales)
));
}
}
/**
* @param string $s
*/
protected function print_msg($s) {
fwrite($this->debug_output, $s . PHP_EOL);
}
}
<?php
namespace PhpAmqpLib\Helper;
class MiscHelper
{
/**
* @param string|array $a
* @return string
*/
public static function methodSig($a)
{
if (is_string($a)) {
return $a;
}
return sprintf('%d,%d', $a[0], $a[1]);
}
/**
* @param string $bytes
*/
public static function saveBytes($bytes)
{
$fh = fopen('/tmp/bytes', 'wb');
fwrite($fh, $bytes);
fclose($fh);
}
/**
* Gets a number (either int or float) and returns an array containing its integer part as first element and its
* decimal part mutliplied by 10^6. Useful for some PHP stream functions that need seconds and microseconds as
* different arguments
*
* @param int|float $number
* @return array
*/
public static function splitSecondsMicroseconds($number)
{
return array(floor($number), ($number - floor($number)) * 1000000);
}
/**
* View any string as a hexdump.
*
* This is most commonly used to view binary data from streams
* or sockets while debugging, but can be used to view any string
* with non-viewable characters.
*
* @version 1.3.2
* @author Aidan Lister <aidan@php.net>
* @author Peter Waller <iridum@php.net>
* @link http://aidanlister.com/repos/v/function.hexdump.php
*
* @param string $data The string to be dumped
* @param bool $htmloutput Set to false for non-HTML output
* @param bool $uppercase Set to true for uppercase hex
* @param bool $return Set to true to return the dump
* @return string|null
*/
public static function hexdump($data, $htmloutput = true, $uppercase = false, $return = false)
{
// Init
$hexi = '';
$ascii = '';
$dump = $htmloutput ? '<pre>' : '';
$offset = 0;
$len = mb_strlen($data, 'ASCII');
// Upper or lower case hexidecimal
$hexFormat = $uppercase ? 'X' : 'x';
// Iterate string
for ($i = $j = 0; $i < $len; $i++) {
// Convert to hexidecimal
// We must use concatenation here because the $hexFormat value
// is needed for sprintf() to parse the format
$hexi .= sprintf('%02' . $hexFormat . ' ', ord($data[$i]));
// Replace non-viewable bytes with '.'
if (ord($data[$i]) >= 32) {
$ascii .= $htmloutput ? htmlentities($data[$i]) : $data[$i];
} else {
$ascii .= '.';
}
// Add extra column spacing
if ($j === 7) {
$hexi .= ' ';
$ascii .= ' ';
}
// Add row
if (++$j === 16 || $i === $len - 1) {
// Join the hexi / ascii output
// We must use concatenation here because the $hexFormat value
// is needed for sprintf() to parse the format
$dump .= sprintf('%04' . $hexFormat . ' %-49s %s', $offset, $hexi, $ascii);
// Reset vars
$hexi = $ascii = '';
$offset += 16;
$j = 0;
// Add newline
if ($i !== $len - 1) {
$dump .= PHP_EOL;
}
}
}
// Finish dump
$dump .= $htmloutput ? '</pre>' : '';
$dump .= PHP_EOL;
if ($return) {
return $dump;
}
echo $dump;
}
/**
* @param array $table
* @return string
*/
public static function dump_table($table)
{
$tokens = array();
foreach ($table as $name => $value) {
switch ($value[0]) {
case 'D':
$val = $value[1]->n . 'E' . $value[1]->e;
break;
case 'F':
$val = '(' . self::dump_table($value[1]) . ')';
break;
case 'T':
$val = date('Y-m-d H:i:s', $value[1]);
break;
default:
$val = $value[1];
}
$tokens[] = $name . '=' . $val;
}
return implode(', ', $tokens);
}
}
<?php
/* This file was autogenerated by spec/parser.php - Do not modify */
namespace PhpAmqpLib\Helper\Protocol;
class MethodMap080
{
/**
* @var array
*/
protected $method_map = array(
'10,10' => 'connection_start',
'10,11' => 'connection_start_ok',
'10,20' => 'connection_secure',
'10,21' => 'connection_secure_ok',
'10,30' => 'connection_tune',
'10,31' => 'connection_tune_ok',
'10,40' => 'connection_open',
'10,41' => 'connection_open_ok',
'10,50' => 'connection_redirect',
'10,60' => 'connection_close',
'10,61' => 'connection_close_ok',
'20,10' => 'channel_open',
'20,11' => 'channel_open_ok',
'20,20' => 'channel_flow',
'20,21' => 'channel_flow_ok',
'20,30' => 'channel_alert',
'20,40' => 'channel_close',
'20,41' => 'channel_close_ok',
'30,10' => 'access_request',
'30,11' => 'access_request_ok',
'40,10' => 'exchange_declare',
'40,11' => 'exchange_declare_ok',
'40,20' => 'exchange_delete',
'40,21' => 'exchange_delete_ok',
'50,10' => 'queue_declare',
'50,11' => 'queue_declare_ok',
'50,20' => 'queue_bind',
'50,21' => 'queue_bind_ok',
'50,30' => 'queue_purge',
'50,31' => 'queue_purge_ok',
'50,40' => 'queue_delete',
'50,41' => 'queue_delete_ok',
'50,50' => 'queue_unbind',
'50,51' => 'queue_unbind_ok',
'60,10' => 'basic_qos',
'60,11' => 'basic_qos_ok',
'60,20' => 'basic_consume',
'60,21' => 'basic_consume_ok',
'60,30' => 'basic_cancel',
'60,31' => 'basic_cancel_ok',
'60,40' => 'basic_publish',
'60,50' => 'basic_return',
'60,60' => 'basic_deliver',
'60,70' => 'basic_get',
'60,71' => 'basic_get_ok',
'60,72' => 'basic_get_empty',
'60,80' => 'basic_ack',
'60,90' => 'basic_reject',
'60,100' => 'basic_recover_async',
'60,110' => 'basic_recover',
'60,111' => 'basic_recover_ok',
'70,10' => 'file_qos',
'70,11' => 'file_qos_ok',
'70,20' => 'file_consume',
'70,21' => 'file_consume_ok',
'70,30' => 'file_cancel',
'70,31' => 'file_cancel_ok',
'70,40' => 'file_open',
'70,41' => 'file_open_ok',
'70,50' => 'file_stage',
'70,60' => 'file_publish',
'70,70' => 'file_return',
'70,80' => 'file_deliver',
'70,90' => 'file_ack',
'70,100' => 'file_reject',
'80,10' => 'stream_qos',
'80,11' => 'stream_qos_ok',
'80,20' => 'stream_consume',
'80,21' => 'stream_consume_ok',
'80,30' => 'stream_cancel',
'80,31' => 'stream_cancel_ok',
'80,40' => 'stream_publish',
'80,50' => 'stream_return',
'80,60' => 'stream_deliver',
'90,10' => 'tx_select',
'90,11' => 'tx_select_ok',
'90,20' => 'tx_commit',
'90,21' => 'tx_commit_ok',
'90,30' => 'tx_rollback',
'90,31' => 'tx_rollback_ok',
'100,10' => 'dtx_select',
'100,11' => 'dtx_select_ok',
'100,20' => 'dtx_start',
'100,21' => 'dtx_start_ok',
'110,10' => 'tunnel_request',
'120,10' => 'test_integer',
'120,11' => 'test_integer_ok',
'120,20' => 'test_string',
'120,21' => 'test_string_ok',
'120,30' => 'test_table',
'120,31' => 'test_table_ok',
'120,40' => 'test_content',
'120,41' => 'test_content_ok',
);
/**
* @var string $method_sig
* @return string
*/
public function get_method($method_sig)
{
return $this->method_map[$method_sig];
}
/**
* @var string $method_sig
* @return bool
*/
public function valid_method($method_sig)
{
return array_key_exists($method_sig, $this->method_map);
}
}
<?php
/* This file was autogenerated by spec/parser.php - Do not modify */
namespace PhpAmqpLib\Helper\Protocol;
class MethodMap091
{
/**
* @var array
*/
protected $method_map = array(
'10,10' => 'connection_start',
'10,11' => 'connection_start_ok',
'10,20' => 'connection_secure',
'10,21' => 'connection_secure_ok',
'10,30' => 'connection_tune',
'10,31' => 'connection_tune_ok',
'10,40' => 'connection_open',
'10,41' => 'connection_open_ok',
'10,50' => 'connection_close',
'10,51' => 'connection_close_ok',
'10,60' => 'connection_blocked',
'10,61' => 'connection_unblocked',
'20,10' => 'channel_open',
'20,11' => 'channel_open_ok',
'20,20' => 'channel_flow',
'20,21' => 'channel_flow_ok',
'20,40' => 'channel_close',
'20,41' => 'channel_close_ok',
'30,10' => 'access_request',
'30,11' => 'access_request_ok',
'40,10' => 'exchange_declare',
'40,11' => 'exchange_declare_ok',
'40,20' => 'exchange_delete',
'40,21' => 'exchange_delete_ok',
'40,30' => 'exchange_bind',
'40,31' => 'exchange_bind_ok',
'40,40' => 'exchange_unbind',
'40,51' => 'exchange_unbind_ok',
'50,10' => 'queue_declare',
'50,11' => 'queue_declare_ok',
'50,20' => 'queue_bind',
'50,21' => 'queue_bind_ok',
'50,30' => 'queue_purge',
'50,31' => 'queue_purge_ok',
'50,40' => 'queue_delete',
'50,41' => 'queue_delete_ok',
'50,50' => 'queue_unbind',
'50,51' => 'queue_unbind_ok',
'60,10' => 'basic_qos',
'60,11' => 'basic_qos_ok',
'60,20' => 'basic_consume',
'60,21' => 'basic_consume_ok',
'60,30' => 'basic_cancel_from_server',
'60,31' => 'basic_cancel_ok',
'60,40' => 'basic_publish',
'60,50' => 'basic_return',
'60,60' => 'basic_deliver',
'60,70' => 'basic_get',
'60,71' => 'basic_get_ok',
'60,72' => 'basic_get_empty',
'60,80' => 'basic_ack_from_server',
'60,90' => 'basic_reject',
'60,100' => 'basic_recover_async',
'60,110' => 'basic_recover',
'60,111' => 'basic_recover_ok',
'60,120' => 'basic_nack_from_server',
'90,10' => 'tx_select',
'90,11' => 'tx_select_ok',
'90,20' => 'tx_commit',
'90,21' => 'tx_commit_ok',
'90,30' => 'tx_rollback',
'90,31' => 'tx_rollback_ok',
'85,10' => 'confirm_select',
'85,11' => 'confirm_select_ok',
);
/**
* @var string $method_sig
* @return string
*/
public function get_method($method_sig)
{
return $this->method_map[$method_sig];
}
/**
* @var string $method_sig
* @return bool
*/
public function valid_method($method_sig)
{
return array_key_exists($method_sig, $this->method_map);
}
}
<?php
/* This file was autogenerated by spec/parser.php - Do not modify */
namespace PhpAmqpLib\Helper\Protocol;
class Wait080
{
/**
* @var array
*/
protected $wait = array(
'connection.start' => '10,10',
'connection.start_ok' => '10,11',
'connection.secure' => '10,20',
'connection.secure_ok' => '10,21',
'connection.tune' => '10,30',
'connection.tune_ok' => '10,31',
'connection.open' => '10,40',
'connection.open_ok' => '10,41',
'connection.redirect' => '10,50',
'connection.close' => '10,60',
'connection.close_ok' => '10,61',
'channel.open' => '20,10',
'channel.open_ok' => '20,11',
'channel.flow' => '20,20',
'channel.flow_ok' => '20,21',
'channel.alert' => '20,30',
'channel.close' => '20,40',
'channel.close_ok' => '20,41',
'access.request' => '30,10',
'access.request_ok' => '30,11',
'exchange.declare' => '40,10',
'exchange.declare_ok' => '40,11',
'exchange.delete' => '40,20',
'exchange.delete_ok' => '40,21',
'queue.declare' => '50,10',
'queue.declare_ok' => '50,11',
'queue.bind' => '50,20',
'queue.bind_ok' => '50,21',
'queue.purge' => '50,30',
'queue.purge_ok' => '50,31',
'queue.delete' => '50,40',
'queue.delete_ok' => '50,41',
'queue.unbind' => '50,50',
'queue.unbind_ok' => '50,51',
'basic.qos' => '60,10',
'basic.qos_ok' => '60,11',
'basic.consume' => '60,20',
'basic.consume_ok' => '60,21',
'basic.cancel' => '60,30',
'basic.cancel_ok' => '60,31',
'basic.publish' => '60,40',
'basic.return' => '60,50',
'basic.deliver' => '60,60',
'basic.get' => '60,70',
'basic.get_ok' => '60,71',
'basic.get_empty' => '60,72',
'basic.ack' => '60,80',
'basic.reject' => '60,90',
'basic.recover_async' => '60,100',
'basic.recover' => '60,110',
'basic.recover_ok' => '60,111',
'file.qos' => '70,10',
'file.qos_ok' => '70,11',
'file.consume' => '70,20',
'file.consume_ok' => '70,21',
'file.cancel' => '70,30',
'file.cancel_ok' => '70,31',
'file.open' => '70,40',
'file.open_ok' => '70,41',
'file.stage' => '70,50',
'file.publish' => '70,60',
'file.return' => '70,70',
'file.deliver' => '70,80',
'file.ack' => '70,90',
'file.reject' => '70,100',
'stream.qos' => '80,10',
'stream.qos_ok' => '80,11',
'stream.consume' => '80,20',
'stream.consume_ok' => '80,21',
'stream.cancel' => '80,30',
'stream.cancel_ok' => '80,31',
'stream.publish' => '80,40',
'stream.return' => '80,50',
'stream.deliver' => '80,60',
'tx.select' => '90,10',
'tx.select_ok' => '90,11',
'tx.commit' => '90,20',
'tx.commit_ok' => '90,21',
'tx.rollback' => '90,30',
'tx.rollback_ok' => '90,31',
'dtx.select' => '100,10',
'dtx.select_ok' => '100,11',
'dtx.start' => '100,20',
'dtx.start_ok' => '100,21',
'tunnel.request' => '110,10',
'test.integer' => '120,10',
'test.integer_ok' => '120,11',
'test.string' => '120,20',
'test.string_ok' => '120,21',
'test.table' => '120,30',
'test.table_ok' => '120,31',
'test.content' => '120,40',
'test.content_ok' => '120,41',
);
/**
* @var string $method
* @return string
*/
public function get_wait($method)
{
return $this->wait[$method];
}
}
<?php
/* This file was autogenerated by spec/parser.php - Do not modify */
namespace PhpAmqpLib\Helper\Protocol;
class Wait091
{
/**
* @var array
*/
protected $wait = array(
'connection.start' => '10,10',
'connection.start_ok' => '10,11',
'connection.secure' => '10,20',
'connection.secure_ok' => '10,21',
'connection.tune' => '10,30',
'connection.tune_ok' => '10,31',
'connection.open' => '10,40',
'connection.open_ok' => '10,41',
'connection.close' => '10,50',
'connection.close_ok' => '10,51',
'connection.blocked' => '10,60',
'connection.unblocked' => '10,61',
'channel.open' => '20,10',
'channel.open_ok' => '20,11',
'channel.flow' => '20,20',
'channel.flow_ok' => '20,21',
'channel.close' => '20,40',
'channel.close_ok' => '20,41',
'access.request' => '30,10',
'access.request_ok' => '30,11',
'exchange.declare' => '40,10',
'exchange.declare_ok' => '40,11',
'exchange.delete' => '40,20',
'exchange.delete_ok' => '40,21',
'exchange.bind' => '40,30',
'exchange.bind_ok' => '40,31',
'exchange.unbind' => '40,40',
'exchange.unbind_ok' => '40,51',
'queue.declare' => '50,10',
'queue.declare_ok' => '50,11',
'queue.bind' => '50,20',
'queue.bind_ok' => '50,21',
'queue.purge' => '50,30',
'queue.purge_ok' => '50,31',
'queue.delete' => '50,40',
'queue.delete_ok' => '50,41',
'queue.unbind' => '50,50',
'queue.unbind_ok' => '50,51',
'basic.qos' => '60,10',
'basic.qos_ok' => '60,11',
'basic.consume' => '60,20',
'basic.consume_ok' => '60,21',
'basic.cancel' => '60,30',
'basic.cancel_ok' => '60,31',
'basic.publish' => '60,40',
'basic.return' => '60,50',
'basic.deliver' => '60,60',
'basic.get' => '60,70',
'basic.get_ok' => '60,71',
'basic.get_empty' => '60,72',
'basic.ack' => '60,80',
'basic.reject' => '60,90',
'basic.recover_async' => '60,100',
'basic.recover' => '60,110',
'basic.recover_ok' => '60,111',
'basic.nack' => '60,120',
'tx.select' => '90,10',
'tx.select_ok' => '90,11',
'tx.commit' => '90,20',
'tx.commit_ok' => '90,21',
'tx.rollback' => '90,30',
'tx.rollback_ok' => '90,31',
'confirm.select' => '85,10',
'confirm.select_ok' => '85,11',
);
/**
* @var string $method
* @return string
*/
public function get_wait($method)
{
return $this->wait[$method];
}
}
<?php
namespace PhpAmqpLib\Message;
use PhpAmqpLib\Wire\GenericContent;
/**
* A Message for use with the Channnel.basic_* methods.
*/
class AMQPMessage extends GenericContent
{
const DELIVERY_MODE_NON_PERSISTENT = 1;
const DELIVERY_MODE_PERSISTENT = 2;
/** @var string */
public $body;
/** @var int */
public $body_size;
/** @var bool */
public $is_truncated = false;
/** @var string */
public $content_encoding;
/** @var array */
protected static $propertyDefinitions = array(
'content_type' => 'shortstr',
'content_encoding' => 'shortstr',
'application_headers' => 'table_object',
'delivery_mode' => 'octet',
'priority' => 'octet',
'correlation_id' => 'shortstr',
'reply_to' => 'shortstr',
'expiration' => 'shortstr',
'message_id' => 'shortstr',
'timestamp' => 'timestamp',
'type' => 'shortstr',
'user_id' => 'shortstr',
'app_id' => 'shortstr',
'cluster_id' => 'shortstr',
);
/**
* @param string $body
* @param array $properties
*/
public function __construct($body = '', $properties = array())
{
$this->setBody($body);
parent::__construct($properties, static::$propertyDefinitions);
}
/**
* @return string
*/
public function getBody()
{
return $this->body;
}
/**
* Sets the message payload
*
* @param string $body
* @return $this
*/
public function setBody($body)
{
$this->body = $body;
return $this;
}
/**
* @return string
*/
public function getContentEncoding()
{
return $this->content_encoding;
}
/**
* @return int
*/
public function getBodySize()
{
return $this->body_size;
}
/**
* @param int $body_size Message body size in byte(s)
* @return AMQPMessage
*/
public function setBodySize($body_size)
{
$this->body_size = (int) $body_size;
return $this;
}
/**
* @return boolean
*/
public function isTruncated()
{
return $this->is_truncated;
}
/**
* @param bool $is_truncated
* @return AMQPMessage
*/
public function setIsTruncated($is_truncated)
{
$this->is_truncated = (bool) $is_truncated;
return $this;
}
}
<?php
namespace PhpAmqpLib\Wire;
class AMQPArray extends AMQPAbstractCollection
{
/**
* @param array|null $data
*/
public function __construct(array $data = null)
{
parent::__construct(empty($data) ? null : array_values($data));
}
/**
* @return int
*/
final public function getType()
{
return self::T_ARRAY;
}
/**
* @param mixed $val
* @param null $type
* @return $this
*/
public function push($val, $type = null)
{
$this->setValue($val, $type);
return $this;
}
}
<?php
namespace PhpAmqpLib\Wire;
use PhpAmqpLib\Exception\AMQPOutOfBoundsException;
/**
* AMQP protocol decimal value.
*
* Values are represented as (n,e) pairs. The actual value
* is n * 10^(-e).
*
* From 0.8 spec: Decimal values are
* not intended to support floating point values, but rather
* business values such as currency rates and amounts. The
* 'decimals' octet is not signed.
*/
class AMQPDecimal
{
/** @var int */
protected $n;
/** @var int */
protected $e;
/**
* @param int $n
* @param int $e
* @throws \PhpAmqpLib\Exception\AMQPOutOfBoundsException
*/
public function __construct($n, $e)
{
if ($e < 0) {
throw new AMQPOutOfBoundsException('Decimal exponent value must be unsigned!');
}
$this->n = $n;
$this->e = $e;
}
/**
* @return string
*/
public function asBCvalue()
{
return bcdiv($this->n, bcpow(10, $this->e));
}
/**
* @return int
*/
public function getE()
{
return $this->e;
}
/**
* @return int
*/
public function getN()
{
return $this->n;
}
}
<?php
namespace PhpAmqpLib\Wire;
use PhpAmqpLib\Exception;
class AMQPTable extends AMQPAbstractCollection
{
/**
* @return int
*/
final public function getType()
{
return self::T_TABLE;
}
/**
* @param string $key
* @param mixed $val
* @param int|null $type
*/
public function set($key, $val, $type = null)
{
//https://www.rabbitmq.com/resources/specs/amqp0-9-1.pdf, https://www.rabbitmq.com/resources/specs/amqp0-8.pdf
//Field names MUST start with a letter, '$' or '#' and may continue with letters, '$' or '#', digits, or underlines, to a maximum length of 128 characters
//The server SHOULD validate field names and upon receiving an invalid field name, it SHOULD signal a connection exception with reply code 503 (syntax error)
//validating length only and delegating other stuff to server, as rabbit seems to currently support numeric keys
if (!($len = strlen($key)) || ($len > 128)) {
throw new Exception\AMQPInvalidArgumentException('Table key must be non-empty string up to 128 chars in length');
}
$this->setValue($val, $type, $key);
}
}
<?php
namespace PhpAmqpLib\Wire;
class AbstractClient
{
/**
* @var bool
*/
protected $is64bits;
/**
* @var bool
*/
protected $isLittleEndian;
public function __construct()
{
$this->is64bits = PHP_INT_SIZE == 8;
$tmp = unpack('S', "\x01\x00"); // to maintain 5.3 compatibility
$this->isLittleEndian = $tmp[1] == 1;
}
/**
* Converts byte-string between native and network byte order, in both directions
*
* @param string $byteStr
* @return string
*/
protected function correctEndianness($byteStr)
{
return $this->isLittleEndian ? strrev($byteStr) : $byteStr;
}
}
<?php
/* This file was autogenerated by spec/parser.php - Do not modify */
namespace PhpAmqpLib\Wire;
class Constants080
{
/**
* @var string
*/
public static $AMQP_PROTOCOL_HEADER = "AMQP\x01\x01\x08\x00";
/**
* @var array
*/
public static $FRAME_TYPES = array(
1 => 'FRAME-METHOD',
2 => 'FRAME-HEADER',
3 => 'FRAME-BODY',
4 => 'FRAME-OOB-METHOD',
5 => 'FRAME-OOB-HEADER',
6 => 'FRAME-OOB-BODY',
7 => 'FRAME-TRACE',
8 => 'FRAME-HEARTBEAT',
4096 => 'FRAME-MIN-SIZE',
206 => 'FRAME-END',
501 => 'FRAME-ERROR',
);
/**
* @var array
*/
public static $CONTENT_METHODS = array(
0 => '60,40',
1 => '60,50',
2 => '60,60',
3 => '60,71',
4 => '70,50',
5 => '70,70',
6 => '80,40',
7 => '80,50',
8 => '80,60',
9 => '110,10',
10 => '120,40',
11 => '120,41',
);
/**
* @var array
*/
public static $CLOSE_METHODS = array(
0 => '10,60',
1 => '20,40',
);
/**
* @var array
*/
public static $GLOBAL_METHOD_NAMES = array(
'10,10' => 'Connection.start',
'10,11' => 'Connection.start_ok',
'10,20' => 'Connection.secure',
'10,21' => 'Connection.secure_ok',
'10,30' => 'Connection.tune',
'10,31' => 'Connection.tune_ok',
'10,40' => 'Connection.open',
'10,41' => 'Connection.open_ok',
'10,50' => 'Connection.redirect',
'10,60' => 'Connection.close',
'10,61' => 'Connection.close_ok',
'20,10' => 'Channel.open',
'20,11' => 'Channel.open_ok',
'20,20' => 'Channel.flow',
'20,21' => 'Channel.flow_ok',
'20,30' => 'Channel.alert',
'20,40' => 'Channel.close',
'20,41' => 'Channel.close_ok',
'30,10' => 'Access.request',
'30,11' => 'Access.request_ok',
'40,10' => 'Exchange.declare',
'40,11' => 'Exchange.declare_ok',
'40,20' => 'Exchange.delete',
'40,21' => 'Exchange.delete_ok',
'50,10' => 'Queue.declare',
'50,11' => 'Queue.declare_ok',
'50,20' => 'Queue.bind',
'50,21' => 'Queue.bind_ok',
'50,30' => 'Queue.purge',
'50,31' => 'Queue.purge_ok',
'50,40' => 'Queue.delete',
'50,41' => 'Queue.delete_ok',
'50,50' => 'Queue.unbind',
'50,51' => 'Queue.unbind_ok',
'60,10' => 'Basic.qos',
'60,11' => 'Basic.qos_ok',
'60,20' => 'Basic.consume',
'60,21' => 'Basic.consume_ok',
'60,30' => 'Basic.cancel',
'60,31' => 'Basic.cancel_ok',
'60,40' => 'Basic.publish',
'60,50' => 'Basic.return',
'60,60' => 'Basic.deliver',
'60,70' => 'Basic.get',
'60,71' => 'Basic.get_ok',
'60,72' => 'Basic.get_empty',
'60,80' => 'Basic.ack',
'60,90' => 'Basic.reject',
'60,100' => 'Basic.recover_async',
'60,110' => 'Basic.recover',
'60,111' => 'Basic.recover_ok',
'70,10' => 'File.qos',
'70,11' => 'File.qos_ok',
'70,20' => 'File.consume',
'70,21' => 'File.consume_ok',
'70,30' => 'File.cancel',
'70,31' => 'File.cancel_ok',
'70,40' => 'File.open',
'70,41' => 'File.open_ok',
'70,50' => 'File.stage',
'70,60' => 'File.publish',
'70,70' => 'File.return',
'70,80' => 'File.deliver',
'70,90' => 'File.ack',
'70,100' => 'File.reject',
'80,10' => 'Stream.qos',
'80,11' => 'Stream.qos_ok',
'80,20' => 'Stream.consume',
'80,21' => 'Stream.consume_ok',
'80,30' => 'Stream.cancel',
'80,31' => 'Stream.cancel_ok',
'80,40' => 'Stream.publish',
'80,50' => 'Stream.return',
'80,60' => 'Stream.deliver',
'90,10' => 'Tx.select',
'90,11' => 'Tx.select_ok',
'90,20' => 'Tx.commit',
'90,21' => 'Tx.commit_ok',
'90,30' => 'Tx.rollback',
'90,31' => 'Tx.rollback_ok',
'100,10' => 'Dtx.select',
'100,11' => 'Dtx.select_ok',
'100,20' => 'Dtx.start',
'100,21' => 'Dtx.start_ok',
'110,10' => 'Tunnel.request',
'120,10' => 'Test.integer',
'120,11' => 'Test.integer_ok',
'120,20' => 'Test.string',
'120,21' => 'Test.string_ok',
'120,30' => 'Test.table',
'120,31' => 'Test.table_ok',
'120,40' => 'Test.content',
'120,41' => 'Test.content_ok',
);
}
<?php
/* This file was autogenerated by spec/parser.php - Do not modify */
namespace PhpAmqpLib\Wire;
class Constants091
{
/**
* @var string
*/
public static $AMQP_PROTOCOL_HEADER = "AMQP\x00\x00\x09\x01";
/**
* @var array
*/
public static $FRAME_TYPES = array(
1 => 'FRAME-METHOD',
2 => 'FRAME-HEADER',
3 => 'FRAME-BODY',
8 => 'FRAME-HEARTBEAT',
4096 => 'FRAME-MIN-SIZE',
206 => 'FRAME-END',
501 => 'FRAME-ERROR',
);
/**
* @var array
*/
public static $CONTENT_METHODS = array(
0 => '60,40',
1 => '60,50',
2 => '60,60',
3 => '60,71',
);
/**
* @var array
*/
public static $CLOSE_METHODS = array(
0 => '10,50',
1 => '20,40',
);
/**
* @var array
*/
public static $GLOBAL_METHOD_NAMES = array(
'10,10' => 'Connection.start',
'10,11' => 'Connection.start_ok',
'10,20' => 'Connection.secure',
'10,21' => 'Connection.secure_ok',
'10,30' => 'Connection.tune',
'10,31' => 'Connection.tune_ok',
'10,40' => 'Connection.open',
'10,41' => 'Connection.open_ok',
'10,50' => 'Connection.close',
'10,51' => 'Connection.close_ok',
'10,60' => 'Connection.blocked',
'10,61' => 'Connection.unblocked',
'20,10' => 'Channel.open',
'20,11' => 'Channel.open_ok',
'20,20' => 'Channel.flow',
'20,21' => 'Channel.flow_ok',
'20,40' => 'Channel.close',
'20,41' => 'Channel.close_ok',
'30,10' => 'Access.request',
'30,11' => 'Access.request_ok',
'40,10' => 'Exchange.declare',
'40,11' => 'Exchange.declare_ok',
'40,20' => 'Exchange.delete',
'40,21' => 'Exchange.delete_ok',
'40,30' => 'Exchange.bind',
'40,31' => 'Exchange.bind_ok',
'40,40' => 'Exchange.unbind',
'40,51' => 'Exchange.unbind_ok',
'50,10' => 'Queue.declare',
'50,11' => 'Queue.declare_ok',
'50,20' => 'Queue.bind',
'50,21' => 'Queue.bind_ok',
'50,30' => 'Queue.purge',
'50,31' => 'Queue.purge_ok',
'50,40' => 'Queue.delete',
'50,41' => 'Queue.delete_ok',
'50,50' => 'Queue.unbind',
'50,51' => 'Queue.unbind_ok',
'60,10' => 'Basic.qos',
'60,11' => 'Basic.qos_ok',
'60,20' => 'Basic.consume',
'60,21' => 'Basic.consume_ok',
'60,30' => 'Basic.cancel',
'60,31' => 'Basic.cancel_ok',
'60,40' => 'Basic.publish',
'60,50' => 'Basic.return',
'60,60' => 'Basic.deliver',
'60,70' => 'Basic.get',
'60,71' => 'Basic.get_ok',
'60,72' => 'Basic.get_empty',
'60,80' => 'Basic.ack',
'60,90' => 'Basic.reject',
'60,100' => 'Basic.recover_async',
'60,110' => 'Basic.recover',
'60,111' => 'Basic.recover_ok',
'60,120' => 'Basic.nack',
'90,10' => 'Tx.select',
'90,11' => 'Tx.select_ok',
'90,20' => 'Tx.commit',
'90,21' => 'Tx.commit_ok',
'90,30' => 'Tx.rollback',
'90,31' => 'Tx.rollback_ok',
'85,10' => 'Confirm.select',
'85,11' => 'Confirm.select_ok',
);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment