├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml ├── src ├── Dynamics │ ├── Constants.php │ ├── Core │ │ └── Log.php │ ├── Dynamics.php │ ├── DynamicsClient.php │ ├── Exception │ │ └── DynamicsException.php │ ├── Http │ │ ├── BaseClient.php │ │ ├── BaseRequest.php │ │ ├── BaseRequestBuilder.php │ │ ├── DynamicsCollectionRequest.php │ │ ├── DynamicsRequest.php │ │ ├── DynamicsResponse.php │ │ ├── EntityRequest.php │ │ ├── EntityRequestBuilder.php │ │ ├── FunctionRequest.php │ │ ├── HeaderOption.php │ │ ├── IBaseClient.php │ │ ├── IBaseRequest.php │ │ ├── IDynamicsClient.php │ │ ├── IEntityRequestBuilder.php │ │ ├── Option.php │ │ └── QueryOption.php │ └── Model │ │ ├── Account.php │ │ ├── AccountLeads.php │ │ ├── ActionCard.php │ │ ├── ActionCardUserState.php │ │ ├── ActivityMimeAttachment.php │ │ ├── ActivityParty.php │ │ ├── ActivityPointer.php │ │ ├── Annotation.php │ │ ├── AnnualFiscalCalendar.php │ │ ├── AppModuleRoles.php │ │ ├── Appointment.php │ │ ├── AsyncOperation.php │ │ ├── Attachment.php │ │ ├── BookableResource.php │ │ ├── BookableResourceBooking.php │ │ ├── BookableResourceBookingHeader.php │ │ ├── BookableResourceCategory.php │ │ ├── BookableResourceCategoryAssn.php │ │ ├── BookableResourceCharacteristic.php │ │ ├── BookableResourceGroup.php │ │ ├── BookingStatus.php │ │ ├── BulkDeleteFailure.php │ │ ├── BulkDeleteOperation.php │ │ ├── BulkOperation.php │ │ ├── BulkOperationLog.php │ │ ├── BusinessUnit.php │ │ ├── BusinessUnitNewsArticle.php │ │ ├── Calendar.php │ │ ├── CalendarRule.php │ │ ├── Campaign.php │ │ ├── CampaignActivity.php │ │ ├── CampaignActivityItem.php │ │ ├── CampaignItem.php │ │ ├── CampaignResponse.php │ │ ├── Category.php │ │ ├── ChannelAccessProfileEntityAccessLevel.php │ │ ├── Characteristic.php │ │ ├── Competitor.php │ │ ├── CompetitorAddress.php │ │ ├── CompetitorProduct.php │ │ ├── CompetitorSalesLiterature.php │ │ ├── ComplexControl.php │ │ ├── Connection.php │ │ ├── ConnectionRole.php │ │ ├── ConnectionRoleAssociation.php │ │ ├── ConstraintBasedGroup.php │ │ ├── Contact.php │ │ ├── ContactInvoices.php │ │ ├── ContactLeads.php │ │ ├── ContactOrders.php │ │ ├── ContactQuotes.php │ │ ├── Contract.php │ │ ├── ContractDetail.php │ │ ├── ContractTemplate.php │ │ ├── CustomControl.php │ │ ├── CustomControlDefaultConfig.php │ │ ├── CustomControlResource.php │ │ ├── CustomerAddress.php │ │ ├── DataPerformance.php │ │ ├── Dependency.php │ │ ├── Discount.php │ │ ├── DiscountType.php │ │ ├── DocumentTemplate.php │ │ ├── DuplicateRecord.php │ │ ├── DuplicateRule.php │ │ ├── DuplicateRuleCondition.php │ │ ├── DynamicProperty.php │ │ ├── DynamicPropertyAssociation.php │ │ ├── DynamicPropertyInstance.php │ │ ├── DynamicPropertyOptionSetItem.php │ │ ├── Email.php │ │ ├── EmailServerProfile.php │ │ ├── Entitlement.php │ │ ├── EntitlementChannel.php │ │ ├── EntitlementContacts.php │ │ ├── EntitlementProducts.php │ │ ├── EntitlementTemplate.php │ │ ├── EntitlementTemplateChannel.php │ │ ├── EntitlementTemplateProducts.php │ │ ├── Equipment.php │ │ ├── ExchangeSyncIdMapping.php │ │ ├── ExpiredProcess.php │ │ ├── Fax.php │ │ ├── Feedback.php │ │ ├── FieldPermission.php │ │ ├── FieldSecurityProfile.php │ │ ├── FixedMonthlyFiscalCalendar.php │ │ ├── Goal.php │ │ ├── GoalRollupQuery.php │ │ ├── Import.php │ │ ├── ImportData.php │ │ ├── ImportEntityMapping.php │ │ ├── ImportFile.php │ │ ├── ImportJob.php │ │ ├── ImportLog.php │ │ ├── ImportMap.php │ │ ├── Incident.php │ │ ├── IncidentKnowledgeBaseRecord.php │ │ ├── IncidentResolution.php │ │ ├── InteractionForEmail.php │ │ ├── InvalidDependency.php │ │ ├── Invoice.php │ │ ├── InvoiceDetail.php │ │ ├── KbArticle.php │ │ ├── KbArticleComment.php │ │ ├── KbArticleTemplate.php │ │ ├── KnowledgeArticle.php │ │ ├── KnowledgeArticleIncident.php │ │ ├── KnowledgeArticleViews.php │ │ ├── KnowledgeArticlesCategories.php │ │ ├── KnowledgeBaseRecord.php │ │ ├── LanguageLocale.php │ │ ├── Lead.php │ │ ├── LeadAddress.php │ │ ├── LeadCompetitors.php │ │ ├── LeadProduct.php │ │ ├── LeadToOpportunitySalesProcess.php │ │ ├── Letter.php │ │ ├── MailMergeTemplate.php │ │ ├── Mailbox.php │ │ ├── MarketingList.php │ │ ├── MarketingListMember.php │ │ ├── Metric.php │ │ ├── MobileOfflineProfile.php │ │ ├── MobileOfflineProfileItem.php │ │ ├── MobileOfflineProfileItemAssociation.php │ │ ├── MonthlyFiscalCalendar.php │ │ ├── NewProcess.php │ │ ├── OfficeGraphDocument.php │ │ ├── Opportunity.php │ │ ├── OpportunityClose.php │ │ ├── OpportunityCompetitors.php │ │ ├── OpportunityProduct.php │ │ ├── OpportunitySalesProcess.php │ │ ├── OrderClose.php │ │ ├── Organization.php │ │ ├── Owner.php │ │ ├── PersonalDocumentTemplate.php │ │ ├── PhoneCall.php │ │ ├── PhoneToCaseProcess.php │ │ ├── PluginAssembly.php │ │ ├── PluginTraceLog.php │ │ ├── PluginType.php │ │ ├── Position.php │ │ ├── Post.php │ │ ├── PostComment.php │ │ ├── PostFollow.php │ │ ├── PostLike.php │ │ ├── PostRegarding.php │ │ ├── PriceLevel.php │ │ ├── PrincipalEntityMap.php │ │ ├── PrincipalObjectAccess.php │ │ ├── Privilege.php │ │ ├── ProcessStage.php │ │ ├── Product.php │ │ ├── ProductAssociation.php │ │ ├── ProductPriceLevel.php │ │ ├── ProductSalesLiterature.php │ │ ├── ProductSubstitute.php │ │ ├── Publisher.php │ │ ├── PublisherAddress.php │ │ ├── QuarterlyFiscalCalendar.php │ │ ├── Queue.php │ │ ├── QueueItem.php │ │ ├── QueueMembership.php │ │ ├── Quote.php │ │ ├── QuoteClose.php │ │ ├── QuoteDetail.php │ │ ├── RatingModel.php │ │ ├── RatingValue.php │ │ ├── RecommendedDocument.php │ │ ├── RecurringAppointmentMaster.php │ │ ├── Report.php │ │ ├── ReportCategory.php │ │ ├── Resource.php │ │ ├── ResourceGroup.php │ │ ├── ResourceSpec.php │ │ ├── Role.php │ │ ├── RolePrivileges.php │ │ ├── RoleTemplate.php │ │ ├── RoleTemplatePrivileges.php │ │ ├── SLA.php │ │ ├── SLAItem.php │ │ ├── SLAKPIInstance.php │ │ ├── SalesLiterature.php │ │ ├── SalesLiteratureItem.php │ │ ├── SalesOrder.php │ │ ├── SalesOrderDetail.php │ │ ├── SavedQuery.php │ │ ├── SavedQueryVisualization.php │ │ ├── SdkMessage.php │ │ ├── SdkMessageFilter.php │ │ ├── SdkMessageProcessingStep.php │ │ ├── SdkMessageProcessingStepImage.php │ │ ├── SdkMessageProcessingStepSecureConfig.php │ │ ├── SemiAnnualFiscalCalendar.php │ │ ├── Service.php │ │ ├── ServiceAppointment.php │ │ ├── ServiceContractContacts.php │ │ ├── ServiceEndpoint.php │ │ ├── SharePointDocumentLocation.php │ │ ├── SharePointSite.php │ │ ├── SimilarityRule.php │ │ ├── Site.php │ │ ├── SocialActivity.php │ │ ├── SocialProfile.php │ │ ├── Solution.php │ │ ├── SolutionComponent.php │ │ ├── Subject.php │ │ ├── SubscriptionManuallyTrackedObject.php │ │ ├── SubscriptionStatisticsOffline.php │ │ ├── SubscriptionStatisticsOutlook.php │ │ ├── SubscriptionSyncEntryOffline.php │ │ ├── SubscriptionSyncEntryOutlook.php │ │ ├── SyncError.php │ │ ├── SystemForm.php │ │ ├── SystemUser.php │ │ ├── SystemUserLicenses.php │ │ ├── SystemUserProfiles.php │ │ ├── SystemUserRoles.php │ │ ├── SystemUserSyncMappingProfiles.php │ │ ├── Task.php │ │ ├── Team.php │ │ ├── TeamMembership.php │ │ ├── TeamProfiles.php │ │ ├── TeamRoles.php │ │ ├── TeamSyncAttributeMappingProfiles.php │ │ ├── TeamTemplate.php │ │ ├── Template.php │ │ ├── Territory.php │ │ ├── Theme.php │ │ ├── TimeStampDateMapping.php │ │ ├── TimeZoneDefinition.php │ │ ├── TimeZoneLocalizedName.php │ │ ├── TimeZoneRule.php │ │ ├── TraceLog.php │ │ ├── TransactionCurrency.php │ │ ├── TranslationProcess.php │ │ ├── UoM.php │ │ ├── UoMSchedule.php │ │ ├── UserForm.php │ │ ├── UserQuery.php │ │ ├── UserQueryVisualization.php │ │ ├── UserSettings.php │ │ ├── WebResource.php │ │ ├── WebWizard.php │ │ ├── Workflow.php │ │ ├── WorkflowLog.php │ │ ├── msdyn_PostAlbum.php │ │ ├── msdyn_PostConfig.php │ │ ├── msdyn_PostRuleConfig.php │ │ ├── msdyn_knowledgearticle_knowledgearticle.php │ │ ├── msdyn_knowledgearticle_knowledgebaserecor.php │ │ ├── msdyn_wallsavedquery.php │ │ └── msdyn_wallsavedqueryusersettings.php └── OData │ ├── Constants.php │ ├── Core │ ├── Enum.php │ └── helpers.php │ ├── Entity.php │ ├── Exception │ ├── ApplicationException.php │ ├── MassAssignmentException.php │ └── ODataException.php │ ├── GuzzleHttpProvider.php │ ├── HeaderOption.php │ ├── HttpMethod.php │ ├── HttpRequestMessage.php │ ├── HttpStatusCode.php │ ├── IAuthenticationProvider.php │ ├── IHttpProvider.php │ ├── IODataClient.php │ ├── IODataRequest.php │ ├── ODataClient.php │ ├── ODataRequest.php │ ├── ODataResponse.php │ ├── Option.php │ ├── Preference.php │ ├── Query │ ├── Builder.php │ ├── Grammar.php │ └── Processor.php │ ├── QueryOption.php │ ├── RequestHeader.php │ ├── ResponseHeader.php │ └── Uri.php ├── tests ├── DynamicsClientTest.php ├── DynamicsTest.php ├── DynamicsTestCase.php ├── Exception │ └── DynamicsExceptionTest.php ├── Http │ ├── DynamicsCollectionTest.php │ ├── DynamicsInstanceTest.php │ ├── DynamicsRequestTest.php │ ├── DynamicsResponseTest.php │ └── HttpTest.php ├── Model │ └── ModelTest.php ├── OData │ ├── ODataClientTest.php │ └── Query │ │ └── BuilderTest.php ├── getTestConfig.bat ├── getTestConfig.sh └── testConfig.example.json └── usage.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.phar 2 | composer.lock 3 | /sdk-generator/ 4 | /vendor/ 5 | /coverage 6 | .idea/ 7 | /storage 8 | .env 9 | .DS_Store 10 | Thumbs.db 11 | /tests/testConfig.json -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | # - '5.3' 5 | # - '5.4' 6 | # - '5.5' 7 | - '5.6' 8 | - '7.0' 9 | - '7.1' 10 | 11 | before_install: 12 | - composer self-update 13 | 14 | install: 15 | - composer install --prefer-source --no-interaction --dev 16 | 17 | script: 18 | - vendor/bin/phpunit -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Saint Systems, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "saintsystems/dynamics-sdk-php", 3 | "version": "0.1.0", 4 | "description": "Saint Systems Microsoft Dynamics 365 SDK for PHP", 5 | "keywords": ["crm", "xrm", "dynamics", "dynamics crm", "dynamics 365", "sdk"], 6 | "homepage": "https://github.com/saintsystems/dynamics-sdk-php", 7 | "license": "MIT", 8 | "type": "library", 9 | "authors": [ 10 | { 11 | "name": "Saint Systems", 12 | "email": "contact@saintsystems.com" 13 | } 14 | ], 15 | "require": { 16 | "php": ">=5.3.0", 17 | "guzzlehttp/guzzle": "^6.2", 18 | "monolog/monolog": "^1.22", 19 | "nesbot/carbon": "^1.22", 20 | "illuminate/support": "^5.4" 21 | }, 22 | "require-dev": { 23 | "phpunit/phpunit": "5.5.*", 24 | "phpdocumentor/phpdocumentor": "^2.9" 25 | }, 26 | "autoload": { 27 | "files": [ 28 | "src/OData/Core/helpers.php", 29 | "tests/DynamicsTestCase.php" 30 | ], 31 | "psr-4": { 32 | "SaintSystems\\OData\\": "src/OData", 33 | "Microsoft\\Dynamics\\": "src/Dynamics" 34 | } 35 | }, 36 | "config": { 37 | "preferred-install": "dist" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | tests 6 | 7 | 8 | 9 | 10 | src 11 | src/Model 12 | 13 | 14 | 17 | -------------------------------------------------------------------------------- /src/Dynamics/Http/FunctionRequest.php: -------------------------------------------------------------------------------- 1 | 8 | /// Gets or sets the content type for the request. 9 | /// 10 | // string ContentType { get; set; } 11 | 12 | // /// 13 | // /// Gets the collection for the request. 14 | // /// 15 | // IList Headers { get; } 16 | 17 | // /// 18 | // /// Gets the for handling requests. 19 | // /// 20 | // IBaseClient Client { get; } 21 | 22 | // /// 23 | // /// Gets or sets the HTTP method string for the request. 24 | // /// 25 | // string Method { get; } 26 | 27 | // /// 28 | // /// Gets the URL for the request, without query string. 29 | // /// 30 | // string RequestUrl { get; } 31 | 32 | /// 33 | /// Gets the collection for the request. 34 | /// 35 | public function getQueryOptions(); 36 | 37 | /// 38 | /// Gets the representation of the request. 39 | /// 40 | /// The representation of the request. 41 | public function getHttpRequestMessage(); 42 | } 43 | -------------------------------------------------------------------------------- /src/Dynamics/Http/IDynamicsClient.php: -------------------------------------------------------------------------------- 1 | name = $name; 10 | $this->value = $value; 11 | } 12 | 13 | public $name; 14 | 15 | public $value; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/Dynamics/Http/QueryOption.php: -------------------------------------------------------------------------------- 1 | value(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/OData/HttpMethod.php: -------------------------------------------------------------------------------- 1 | value(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/OData/HttpRequestMessage.php: -------------------------------------------------------------------------------- 1 | method = $method; 52 | $this->requestUri = $requestUri; 53 | $this->headers = []; 54 | $this->returnsStream = false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/OData/IAuthenticationProvider.php: -------------------------------------------------------------------------------- 1 | 8 | /// Gets a serializer for serializing and deserializing JSON objects. 9 | /// 10 | //ISerializer Serializer { get; } 11 | 12 | /** 13 | * Sends the request. 14 | * @param HttpRequestMessage $request The HttpRequestMessage to send. 15 | * @return HttpResponseMessage The HttpResponseMessage. 16 | */ 17 | public function send(HttpRequestMessage $request); 18 | 19 | /// 20 | /// Sends the request. 21 | /// 22 | /// The to send. 23 | /// The to pass to the on send. 24 | /// The for the request. 25 | /// The . 26 | // public function sendAsync( 27 | // HttpRequestMessage request, 28 | // HttpCompletionOption completionOption, 29 | // CancellationToken cancellationToken); 30 | } 31 | -------------------------------------------------------------------------------- /src/OData/IODataClient.php: -------------------------------------------------------------------------------- 1 | 8 | /// Gets or sets the content type for the request. 9 | /// 10 | // string ContentType { get; set; } 11 | 12 | // /// 13 | // /// Gets the collection for the request. 14 | // /// 15 | // IList Headers { get; } 16 | 17 | // /// 18 | // /// Gets the for handling requests. 19 | // /// 20 | // IBaseClient Client { get; } 21 | 22 | // /// 23 | // /// Gets or sets the HTTP method string for the request. 24 | // /// 25 | // string Method { get; } 26 | 27 | // /// 28 | // /// Gets the URL for the request, without query string. 29 | // /// 30 | // string RequestUrl { get; } 31 | 32 | /// 33 | /// Gets the collection for the request. 34 | /// 35 | //public function getQueryOptions(); 36 | 37 | /// 38 | /// Gets the representation of the request. 39 | /// 40 | /// The representation of the request. 41 | public function getHttpRequestMessage(); 42 | } 43 | -------------------------------------------------------------------------------- /src/OData/Option.php: -------------------------------------------------------------------------------- 1 | name = $name; 10 | $this->value = $value; 11 | } 12 | 13 | public $name; 14 | 15 | public $value; 16 | } 17 | -------------------------------------------------------------------------------- /src/OData/Preference.php: -------------------------------------------------------------------------------- 1 | value(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/OData/Query/Processor.php: -------------------------------------------------------------------------------- 1 | getClient()->insert($sql, $values); 31 | 32 | $id = $query->getConnection()->getPdo()->lastInsertId($sequence); 33 | 34 | return is_numeric($id) ? (int) $id : $id; 35 | } 36 | 37 | /** 38 | * Process the results of a column listing query. 39 | * 40 | * @param array $results 41 | * @return array 42 | */ 43 | public function processColumnListing($results) 44 | { 45 | return $results; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/OData/QueryOption.php: -------------------------------------------------------------------------------- 1 | value(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/OData/ResponseHeader.php: -------------------------------------------------------------------------------- 1 | value(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/OData/Uri.php: -------------------------------------------------------------------------------- 1 | parsed = $uriParsed; 41 | foreach(self::URI_PARTS as $uriPart) { 42 | if (isset($uriParsed[$uriPart])) { 43 | $this->$uriPart = $uriParsed[$uriPart]; 44 | } 45 | } 46 | 47 | } 48 | 49 | public function __toString() 50 | { 51 | return http_build_url($this->parsed); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/Exception/DynamicsExceptionTest.php: -------------------------------------------------------------------------------- 1 | assertEquals("Microsoft\Dynamics\Exception\DynamicsException: [404]: bad stuff\n", $exception->__toString()); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/getTestConfig.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | SET testConfig={ 4 | SET testConfig=%testConfig% "test_client_id_v1": "%TEST_CLIENT_ID_V1%", 5 | SET testConfig=%testConfig% "test_client_secret_v1": "%TEST_CLIENT_SECRET_V1%", 6 | SET testConfig=%testConfig% "test_client_id_v2": "%TEST_CLIENT_ID_V2%", 7 | SET testConfig=%testConfig% "test_client_secret_v2": "%TEST_CLIENT_SECRET_V2%", 8 | SET testConfig=%testConfig% "test_username": "%TEST_USERNAME%", 9 | SET testConfig=%testConfig% "test_password": "%1", 10 | SET testConfig=%testConfig% "test_instance_url": "%TEST_INSTANCE_URL%" 11 | SET testConfig=%testConfig% } 12 | echo %testConfig% 13 | echo %testConfig% > testConfig.example.json 14 | -------------------------------------------------------------------------------- /tests/getTestConfig.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | testConfig="{ 4 | \"test_client_id_v1\": \"$test_client_id_v1\", 5 | \"test_client_secret_v1\": \"$test_client_secret_v1\", 6 | \"test_client_id_v2\": \"$test_client_id_v2\", 7 | \"test_client_secret_v2\": \"$test_client_secret_v2\", 8 | \"test_username\": \"$test_username\", 9 | \"test_password\": \"$1\", 10 | \"test_instance_url\": \"$test_instance_url\" 11 | }" 12 | echo $testConfig 13 | echo $testConfig > testConfig.example.json 14 | -------------------------------------------------------------------------------- /tests/testConfig.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "test_client_id_v1": "", 3 | "test_client_secret_v1": "", 4 | "test_client_id_v2": "", 5 | "test_client_secret_v2": "", 6 | "test_username": "", 7 | "test_password": "", 8 | "test_instance_url": "" 9 | } 10 | --------------------------------------------------------------------------------