这两周导师一直在美国,所以联系起来很不方便,加上现有的资料很少,所以只能自己摸索,上周确定了思路,导师也说思路是正确的,那么这周就要对代码进行改写。
要改写的代码包括IDataServiceMetaDataProvider,IDataServiceQuery Provider,IDataServiceQueryProvider2,IServiceProvider ,IExpressionProvider,Metadata Mapping这几个部分,每一个部分的功能在上周的报告中已经说过,这里就不在赘述,那么我们一个个来。
首先是IDataServiceMetaDataProvider,用来描述实体集和实体的属性及实体间的联系,我们选择SugarCRM中的Contacts实体,首先定义Contacts实体,我们选取
id; 序号
first_name; 名
last_name; 姓
phone_mobile;手机
phone_fax; 传真
primary_address_street; 地址-街道
primary_address_city;地址-城市
primary_address_country;地址-国家
birthdate; 生日
其中id为主键,下面会用到
class Contacts
{
//Key Edm.Int32
public $id;
//Edm.String
public $first_name;
//Edm.String
public $last_name;
//Edm.String
public $phone_mobile;
//Edm.String
public $phone_fax;
//Edm.String
public $primary_address_street;
//Edm.String
public $primary_address_city;
//Edm.String
public $primary_address_country;
//Edm.String
public $birthdate;
//Edm.String
}
然后创建元数据类class CreateSugarCRMMetadata
public static function create()
{
$metadata = new ServiceBaseMetadata('SugarCRMEntities', 'SugarCRM');
//Register the entity (resource) type 'Contacts'
$ContactsEntityType = $metadata->addEntityType(new ReflectionClass('Contacts'), 'Contacts', 'SugarCRM');
$metadata->addKeyProperty($ContactsEntityType, 'id', EdmPrimitiveType::INT32);
$metadata->addPrimitiveProperty($ContactsEntityType, 'first_name', EdmPrimitiveType::STRING);
$metadata->addPrimitiveProperty($ContactsEntityType, 'last_name', EdmPrimitiveType::STRING);
$metadata->addPrimitiveProperty($ContactsEntityType, 'primary_address_street', EdmPrimitiveType::STRING);
$metadata->addPrimitiveProperty($ContactsEntityType, 'primary_address_city', EdmPrimitiveType::STRING);
$metadata->addPrimitiveProperty($ContactsEntityType, 'primary_address_country', EdmPrimitiveType::STRING);
$metadata->addPrimitiveProperty($ContactsEntityType, 'phone_mobile', EdmPrimitiveType::STRING);
$metadata->addPrimitiveProperty($ContactsEntityType, 'phone_fax', EdmPrimitiveType::STRING);
$metadata->addPrimitiveProperty($ContactsEntityType, 'birthdate', EdmPrimitiveType::DATETIME);
$ContactsResourceSet = $metadata->addResourceSet('Contacts', $ContactsEntityType);
return $metadata;
}
首先初始化了metadata对象,继承基类ServiceBaseMetadata,为其添加实体Contacts
然后为实体添加属性,分别为上面我们定义的属性,除了id使用添加主键的方法addKeyProperty,其他调用addPrimitiveProperty函数,最后将实体Contacts加入实体集
然后我们看IDataServiceQuery Provider和IDataServiceQuery Provider2这里我们直接用IDataServiceQuery Provider2
首先定义MySQL配置
/** The name of the database for WordPress */
define('DB_NAME', 'SugarCRM');
/** MySQL database username */
define('DB_USER', 'root');
/** MySQL database password */
define('DB_PASSWORD', '');
/** MySQL hostname */
define('DB_HOST', 'localhost');
在构造函数中连接数据库
public function __construct()
{
$this->_connectionHandle = @mysql_connect(DB_HOST, DB_USER, DB_PASSWORD, true);
if ( $this->_connectionHandle ) {
} else {
die(print_r(mysql_error(), true));
}
mysql_select_db(DB_NAME, $this->_connectionHandle);
}
IDataServiceQuery Provider2中有5个方法,这里我们只用到两个
第一个是getResourceSet(ResourceSet $resourceSet,$filter=null,$select=null,$orderby=null,$top=null,$skip=null),这个函数返回经过过滤器筛选的结果
public function getResourceSet(ResourceSet $resourceSet,$filter=null,$select=null,$orderby=null,$top=null,$skip=null)
{
ODataException::createNotImplementedError($this->_message);
$resourceSetName = $resourceSet->getName();
if ($resourceSetName !== 'Contacts'
) {
die('(SugarCRMQueryProvider) Unknown resource set ' . $resourceSetName);
}
$returnResult = array();
switch ($resourceSetName) {
case 'Contacts':
$query = "SELECT * FROM `contacts`";
if ($filter !== null) {
$query .= " AND $filter";
}
$stmt = mysql_query($query);
$returnResult = $this->_serializeContacts($stmt);
break;
}
mysql_free_result($stmt);
return $returnResult;
}
这里stmt为执行sql语句返回的结果,作为_serializeContacts函数的参数,_serializeContacts参数用于将结果传入一个Contacts对象中
private function _serializeContacts($record)
{
$contacts = new Contacts();
$contacts->id = $record['id'];
$contacts->first_name = $record['first_name'];
$contacts->last_name = $record['last_name'];
$contacts->phone_mobile = $record['phone_mobile'];
$contacts->phone_fax = $record['phone_fax'];
$contacts->primary_address_street = $record['primary_address_street'];
$contacts->primary_address_city = $record['primary_address_city'];
$contacts->primary_address_county = $record['primary_address_county'];
if (!is_null($record['birthdate'])) {
$dateTime = new DateTime($record['birthdate']);
$contacts->birthdate = $dateTime->format('Y-m-d\TH:i:s');
} else {
$contacts->birthdate = null;
}
return $contacts;
}
而getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)则是带有关键字的查询
public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
{
ODataException::createNotImplementedError($this->_message);
$resourceSetName = $resourceSet->getName();
if ($resourceSetName !== 'Contacts'
) {
die('(WordPressQueryProvider) Unknown resource set ' . $resourceSetName);
}
$namedKeyValues = $keyDescriptor->getValidatedNamedValues();
$condition = null;
foreach ($namedKeyValues as $key => $value) {
$condition .= $key . ' = ' . $value[0] . ' and ';
}
$len = strlen($condition);
$condition = substr($condition, 0, $len - 5);
$query = "SELECT * FROM [$resourceSetName] WHERE $condition";
$stmt = mysql_query($query);
if (!mysql_num_rows($stmt)) {
return null;
}
$data = mysql_fetch_assoc($stmt);
switch ($resourceSetName) {
case 'Contacts':
$result = $this->_serializeContacts($data);
break;
}
mysql_free_result($stmt);
return $result;
}
其中$keyDescriptor->getValidatedNamedValues()返回关键字数组,然后用循环取得关键字及对应的值
下面改写IDataService,分别改写
public function getService($serviceType)
{
if(($serviceType === 'IDataServiceMetadataProvider') ||
($serviceType === 'IDataServiceQueryProvider2') ||
($serviceType === 'IDataServiceStreamProvider')) {
if (is_null($this->_SugarCRMExpressionProvider)) {
$this->_SugarCRMExpressionProvider = new SugarCRMDSExpressionProvider();
}
}
if ($serviceType === 'IDataServiceMetadataProvider') {
if (is_null($this->_SugarCRMMetadata)) {
$this->_SugarCRMMetadata = CreateSugarCRMMetadata::create();
// $this->_SugarCRMMetadata->mappedDetails = CreateSugarCRMMetadata::mappingInitialize();
}
return $this->_SugarCRMMetadata;
} else if ($serviceType === 'IDataServiceQueryProvider2') {
if (is_null($this->_SugarCRMQueryProvider)) {
$this->_SugarCRMQueryProvider = new SugarCRMQueryProvider();
}
return $this->_SugarCRMQueryProvider;
} else if ($serviceType === 'IDataServiceStreamProvider') {
return new SugarCRMStreamProvider();
}
return null;
}
// For testing we overridden the DataService::handleRequest method, one thing is the
// private memeber variable DataService::_dataServiceHost is not accessible in this class,
// so we are using getHost() below.
public function handleRequest()
{
try {
$this->createProviders();
$this->getHost()->validateQueryParameters();
$requestMethod = $this->getOperationContext()->incomingRequest()->getMethod();
if ($requestMethod !== ODataConstants::HTTP_METHOD_GET) {
ODataException::createNotImplementedError(Messages::dataServiceOnlyReadSupport($requestMethod));
}
} catch (\Exception $exception) {
throw $exception;
}
$uriProcessor = null;
try {
$uriProcessor = UriProcessor::process($this);
return $uriProcessor;
} catch (\Exception $exception) {
throw $exception;
}
}
这两个函数,将metadata,queryprovider连接起来。
下一步的测试还需要跟导师沟通,下周将进行初步的测试。