212 lines
5.4 KiB
PHP
212 lines
5.4 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace App\Entity\Parse;
|
||
|
|
|
||
|
|
use App\Model\Model as Entity;
|
||
|
|
use App\Model\Company;
|
||
|
|
use App\Model\Platform;
|
||
|
|
use App\Model\Store;
|
||
|
|
use App\Entity\Parse\Traits\EntityParseHelper;
|
||
|
|
use Hyperf\Amqp\Message\ConsumerMessageInterface;
|
||
|
|
use InvalidArgumentException;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* EntityParse 抽象类
|
||
|
|
*
|
||
|
|
* 使用工厂方法模式 + 延迟初始化
|
||
|
|
* 提供消息解析的通用框架和默认实现
|
||
|
|
*
|
||
|
|
* @method static static create(ConsumerMessageInterface $message)
|
||
|
|
*/
|
||
|
|
abstract class EntityParse implements EntityParseInterface
|
||
|
|
{
|
||
|
|
use EntityParseHelper;
|
||
|
|
|
||
|
|
protected ConsumerMessageInterface $message;
|
||
|
|
protected ?Platform $platform = null;
|
||
|
|
protected ?Company $company = null;
|
||
|
|
protected ?Store $store = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 禁止直接使用构造函数
|
||
|
|
* 使用 create() 工厂方法创建实例
|
||
|
|
*/
|
||
|
|
protected function __construct()
|
||
|
|
{
|
||
|
|
// 空构造函数,延迟初始化
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 工厂方法:创建解析器实例
|
||
|
|
*
|
||
|
|
* @param ConsumerMessageInterface $message
|
||
|
|
* @return static
|
||
|
|
* @throws InvalidArgumentException
|
||
|
|
*/
|
||
|
|
public static function create(ConsumerMessageInterface $message): static
|
||
|
|
{
|
||
|
|
$instance = new static();
|
||
|
|
$instance->message = $message;
|
||
|
|
$instance->initialize();
|
||
|
|
return $instance;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 延迟初始化
|
||
|
|
* 在 message 设置后执行作用域匹配和验证
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
* @throws InvalidArgumentException
|
||
|
|
*/
|
||
|
|
protected function initialize(): void
|
||
|
|
{
|
||
|
|
$this->platform = $this->platformScopeMatch($this->message);
|
||
|
|
$this->company = $this->companyScopeMatch($this->message);
|
||
|
|
$this->store = $this->storeScopeMatch($this->message);
|
||
|
|
|
||
|
|
$this->validateScope();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 验证作用域对象是否有效
|
||
|
|
*
|
||
|
|
* @return void
|
||
|
|
* @throws InvalidArgumentException
|
||
|
|
*/
|
||
|
|
protected function validateScope(): void
|
||
|
|
{
|
||
|
|
if (!$this->platform instanceof Platform || !isset($this->platform->id)) {
|
||
|
|
throw new InvalidArgumentException('Platform is undefined or invalid');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!$this->company instanceof Company || !isset($this->company->id)) {
|
||
|
|
throw new InvalidArgumentException('Company is undefined or invalid');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!$this->store instanceof Store || !isset($this->store->id)) {
|
||
|
|
throw new InvalidArgumentException('Store is undefined or invalid');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 平台作用域匹配 - 提供默认实现
|
||
|
|
*
|
||
|
|
* 从 exchange 名称中提取平台信息
|
||
|
|
* 子类可以覆盖此方法以实现自定义逻辑
|
||
|
|
*
|
||
|
|
* @param ConsumerMessageInterface $message
|
||
|
|
* @return Platform
|
||
|
|
* @throws InvalidArgumentException
|
||
|
|
*/
|
||
|
|
public function platformScopeMatch(ConsumerMessageInterface $message): Platform
|
||
|
|
{
|
||
|
|
return $this->extractPlatformFromExchange($message);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 实体匹配 - 提供默认实现
|
||
|
|
*
|
||
|
|
* 从 routing key 中提取实体类型
|
||
|
|
* 子类可以覆盖此方法以实现自定义逻辑
|
||
|
|
*
|
||
|
|
* @param ConsumerMessageInterface $message
|
||
|
|
* @return Entity
|
||
|
|
* @throws InvalidArgumentException
|
||
|
|
*/
|
||
|
|
public function entityMatch(ConsumerMessageInterface $message): Entity
|
||
|
|
{
|
||
|
|
return $this->extractEntityFromRoutingKey($message);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 唯一标识符提取 - 提供默认实现
|
||
|
|
*
|
||
|
|
* 默认从消息体中提取 id 或 unique_id
|
||
|
|
* 子类可以覆盖此方法以实现自定义逻辑
|
||
|
|
*
|
||
|
|
* @param ConsumerMessageInterface $message
|
||
|
|
* @return string|int
|
||
|
|
* @throws InvalidArgumentException
|
||
|
|
*/
|
||
|
|
public function entityUniqueIdentifierExtract(ConsumerMessageInterface $message): string|int
|
||
|
|
{
|
||
|
|
$data = $this->extractMessageData($message);
|
||
|
|
return $this->extractUniqueIdentifier($data);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 公司作用域匹配 - 抽象方法
|
||
|
|
*
|
||
|
|
* 必须由子类实现,因为不同平台的公司识别逻辑不同
|
||
|
|
*
|
||
|
|
* @param ConsumerMessageInterface $message
|
||
|
|
* @return Company
|
||
|
|
*/
|
||
|
|
abstract public function companyScopeMatch(ConsumerMessageInterface $message): Company;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 店铺作用域匹配 - 抽象方法
|
||
|
|
*
|
||
|
|
* 必须由子类实现,因为不同平台的店铺识别逻辑不同
|
||
|
|
*
|
||
|
|
* @param ConsumerMessageInterface $message
|
||
|
|
* @return Store
|
||
|
|
*/
|
||
|
|
abstract public function storeScopeMatch(ConsumerMessageInterface $message): Store;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 实体数据映射 - 抽象方法
|
||
|
|
*
|
||
|
|
* 必须由子类实现,因为不同平台的数据结构不同
|
||
|
|
*
|
||
|
|
* @param array $data
|
||
|
|
* @param Entity $entity
|
||
|
|
* @return Entity
|
||
|
|
*/
|
||
|
|
abstract public function entityMap(array $data, Entity $entity): Entity;
|
||
|
|
|
||
|
|
// ==================== Getter 方法 ====================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 获取消息对象
|
||
|
|
*
|
||
|
|
* @return ConsumerMessageInterface
|
||
|
|
*/
|
||
|
|
public function getMessage(): ConsumerMessageInterface
|
||
|
|
{
|
||
|
|
return $this->message;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 获取平台对象
|
||
|
|
*
|
||
|
|
* @return Platform
|
||
|
|
*/
|
||
|
|
public function getPlatform(): Platform
|
||
|
|
{
|
||
|
|
return $this->platform;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 获取公司对象
|
||
|
|
*
|
||
|
|
* @return Company
|
||
|
|
*/
|
||
|
|
public function getCompany(): Company
|
||
|
|
{
|
||
|
|
return $this->company;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 获取店铺对象
|
||
|
|
*
|
||
|
|
* @return Store
|
||
|
|
*/
|
||
|
|
public function getStore(): Store
|
||
|
|
{
|
||
|
|
return $this->store;
|
||
|
|
}
|
||
|
|
}
|