diff --git a/.gitignore b/.gitignore index 7bdd89c..701e607 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ composer.lock .php_cs.cache /.idea/ .phpunit.result.cache +.phpunit.cache/ diff --git a/.php-cs-fixer.cache b/.php-cs-fixer.cache index bdcd3b3..f914dcf 100644 --- a/.php-cs-fixer.cache +++ b/.php-cs-fixer.cache @@ -1 +1 @@ -{"php":"8.1.5","version":"3.9.6-DEV:dev-master#22804e82950a7d80f1185872c8396fca1c675f45","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"align_single_space"},"blank_line_after_namespace":true,"blank_line_after_opening_tag":true,"blank_line_before_statement":{"statements":["return"]},"braces":true,"cast_spaces":true,"class_definition":true,"concat_space":true,"declare_equal_normalize":true,"elseif":true,"encoding":true,"no_extra_blank_lines":true,"full_opening_tag":true,"function_declaration":true,"function_typehint_space":true,"heredoc_to_nowdoc":true,"include":true,"indentation_type":true,"line_ending":true,"lowercase_cast":true,"single_line_comment_style":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ensure_fully_multiline"},"multiline_whitespace_before_semicolons":true,"native_function_casing":true,"new_with_braces":true,"linebreak_after_opening_tag":true,"no_alias_functions":true,"no_blank_lines_after_class_opening":true,"no_blank_lines_after_phpdoc":true,"no_closing_tag":true,"no_empty_comment":true,"no_empty_phpdoc":true,"no_empty_statement":true,"no_leading_import_slash":true,"no_leading_namespace_whitespace":true,"no_mixed_echo_print":true,"no_multiline_whitespace_around_double_arrow":true,"no_short_bool_cast":true,"no_singleline_whitespace_before_semicolons":true,"no_spaces_after_function_name":true,"no_spaces_around_offset":true,"no_spaces_inside_parenthesis":true,"no_trailing_comma_in_list_call":true,"no_trailing_comma_in_singleline_array":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"no_unneeded_control_parentheses":true,"no_unreachable_default_argument_value":true,"no_unused_imports":true,"no_useless_else":true,"no_useless_return":true,"no_whitespace_before_comma_in_array":true,"no_whitespace_in_blank_line":true,"normalize_index_brace":true,"object_operator_without_whitespace":true,"ordered_imports":true,"php_unit_construct":true,"php_unit_dedicate_assert":true,"php_unit_fqcn_annotation":true,"phpdoc_add_missing_param_annotation":true,"phpdoc_align":true,"phpdoc_annotation_without_dot":true,"phpdoc_indent":true,"general_phpdoc_tag_rename":true,"phpdoc_inline_tag_normalizer":true,"phpdoc_tag_type":true,"phpdoc_no_access":true,"phpdoc_no_empty_return":true,"phpdoc_no_package":true,"phpdoc_order":true,"phpdoc_scalar":true,"phpdoc_separation":true,"phpdoc_single_line_var_spacing":true,"phpdoc_summary":true,"phpdoc_to_comment":true,"phpdoc_trim":true,"phpdoc_no_alias_tag":true,"phpdoc_types":true,"phpdoc_var_without_name":true,"pow_to_exponentiation":true,"increment_style":{"style":"pre"},"psr_autoloading":true,"random_api_migration":true,"return_type_declaration":true,"self_accessor":true,"semicolon_after_instruction":true,"array_syntax":{"syntax":"short"},"short_scalar_cast":true,"error_suppression":true,"single_blank_line_at_eof":true,"single_blank_line_before_namespace":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"single_quote":true,"space_after_semicolon":true,"standardize_not_equals":true,"strict_comparison":true,"strict_param":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"ternary_operator_spaces":true,"trailing_comma_in_multiline":{"elements":["arrays"]},"trim_array_spaces":true,"unary_operator_spaces":true,"visibility_required":{"elements":["method","property"]},"whitespace_after_comma_in_array":true,"constant_case":true,"no_break_comment":true,"no_space_around_double_colon":true},"hashes":{"src\\Exception\\DeviceApiCallException.php":397307940,"src\\Exception\\InvalidCardPermissionsException.php":3194439575,"src\\Exception\\InvalidSsmlException.php":274108870,"src\\Exception\\MissingRequestDataException.php":489670375,"src\\Exception\\MissingRequestHandlerException.php":2510768499,"src\\Exception\\MissingRequiredHeaderException.php":3635596926,"src\\Exception\\OutdatedCertExceptionException.php":2732495116,"src\\Exception\\RequestInvalidSignatureException.php":3596342060,"src\\Exception\\RequestInvalidTimestampException.php":2346064383,"src\\Helper\\DeviceAddressInformationHelper.php":83807951,"src\\Helper\\ResponseHelper.php":3687729275,"src\\Helper\\SsmlGenerator.php":1288062931,"src\\Helper\\SsmlTypes.php":954324338,"src\\Intent\\Intent.php":767475374,"src\\Intent\\IntentStatus.php":653912920,"src\\Intent\\IntentValue.php":1530434202,"src\\Intent\\Resolution.php":724455019,"src\\Intent\\Slot.php":1998609919,"src\\Request\\Altitude.php":4272229216,"src\\Request\\Application.php":908255488,"src\\Request\\AudioPlayer.php":1477811147,"src\\Request\\Context.php":3142905282,"src\\Request\\Coordinate.php":1555575182,"src\\Request\\Device\\DeviceAddressInformation.php":560156306,"src\\Request\\Device.php":4251527235,"src\\Request\\Geolocation.php":3293137606,"src\\Request\\Heading.php":2684314193,"src\\Request\\LocationServices.php":1012151918,"src\\Request\\Request\\AbstractRequest.php":1863190066,"src\\Request\\Request\\AlexaSkillEvent\\AlexaSkillEventRequest.php":1595930221,"src\\Request\\Request\\AlexaSkillEvent\\Permission.php":2816409009,"src\\Request\\Request\\AlexaSkillEvent\\SkillAccountLinkedBody.php":3031065602,"src\\Request\\Request\\AlexaSkillEvent\\SkillAccountLinkedRequest.php":762195851,"src\\Request\\Request\\AlexaSkillEvent\\SkillDisabledBody.php":146513525,"src\\Request\\Request\\AlexaSkillEvent\\SkillDisabledRequest.php":4133461499,"src\\Request\\Request\\AlexaSkillEvent\\SkillEnabledRequest.php":3393486954,"src\\Request\\Request\\AlexaSkillEvent\\SkillPermissionAcceptedRequest.php":22183186,"src\\Request\\Request\\AlexaSkillEvent\\SkillPermissionBody.php":2058528688,"src\\Request\\Request\\AlexaSkillEvent\\SkillPermissionChangedRequest.php":1830336513,"src\\Request\\Request\\AudioPlayer\\AudioPlayerRequest.php":809219092,"src\\Request\\Request\\AudioPlayer\\PlaybackFailedRequest.php":1518761903,"src\\Request\\Request\\AudioPlayer\\PlaybackFinishedRequest.php":652913643,"src\\Request\\Request\\AudioPlayer\\PlaybackNearlyFinishedRequest.php":2302787869,"src\\Request\\Request\\AudioPlayer\\PlaybackStartedRequest.php":1345970560,"src\\Request\\Request\\AudioPlayer\\PlaybackState.php":2889732258,"src\\Request\\Request\\AudioPlayer\\PlaybackStoppedRequest.php":3947833879,"src\\Request\\Request\\CanFulfill\\CanFulfillIntentRequest.php":3659921764,"src\\Request\\Request\\Display\\ElementSelectedRequest.php":1321680358,"src\\Request\\Request\\Error.php":639069852,"src\\Request\\Request\\GameEngine\\Event\\Event.php":1832495237,"src\\Request\\Request\\GameEngine\\Event\\InputEvent.php":3897164627,"src\\Request\\Request\\GameEngine\\InputHandlerEvent.php":3895611239,"src\\Request\\Request\\PlaybackController\\AbstractPlaybackController.php":1036205313,"src\\Request\\Request\\PlaybackController\\NextCommandIssued.php":3192103095,"src\\Request\\Request\\PlaybackController\\PauseCommandIssued.php":1592392333,"src\\Request\\Request\\PlaybackController\\PlayCommandIssued.php":1675200176,"src\\Request\\Request\\PlaybackController\\PreviousCommandIssued.php":563877389,"src\\Request\\Request\\Standard\\IntentRequest.php":2838266080,"src\\Request\\Request\\Standard\\LaunchRequest.php":1376844276,"src\\Request\\Request\\Standard\\SessionEndedRequest.php":2221840009,"src\\Request\\Request\\Standard\\StandardRequest.php":106014074,"src\\Request\\Request\\System\\Cause.php":1406376195,"src\\Request\\Request\\System\\ConnectionsResponseRequest.php":1686197248,"src\\Request\\Request\\System\\ExceptionEncounteredRequest.php":3022964728,"src\\Request\\Request\\System\\Payload.php":4092526878,"src\\Request\\Request\\System\\Status.php":3091189016,"src\\Request\\Request\\System\\SystemRequest.php":749011239,"src\\Request\\Request.php":594739231,"src\\Request\\Session.php":2534237904,"src\\Request\\Speed.php":1695802154,"src\\Request\\System.php":1686479837,"src\\Request\\User.php":2294250240,"src\\Request\\UserPermissions.php":4070448573,"src\\RequestHandler\\AbstractRequestHandler.php":832848863,"src\\RequestHandler\\Basic\\CancelRequestHandler.php":442988638,"src\\RequestHandler\\Basic\\ExceptionEncounteredRequestHandler.php":3607095168,"src\\RequestHandler\\Basic\\HelpRequestHandler.php":2436916006,"src\\RequestHandler\\Basic\\NavigateHomeRequestHandler.php":2260083906,"src\\RequestHandler\\Basic\\SessionEndedRequestHandler.php":2730579585,"src\\RequestHandler\\Basic\\StopRequestHandler.php":3796312275,"src\\RequestHandler\\RequestHandlerRegistry.php":938829433,"src\\Response\\CanFulfill\\CanFulfillIntentResponse.php":11474660,"src\\Response\\CanFulfill\\CanFulfillResponseBody.php":357970446,"src\\Response\\CanFulfill\\CanFulfillSlot.php":168508376,"src\\Response\\Card.php":2075215240,"src\\Response\\CardImage.php":2488769290,"src\\Response\\Directives\\AudioPlayer\\AudioItem.php":260504635,"src\\Response\\Directives\\AudioPlayer\\ClearDirective.php":3467354814,"src\\Response\\Directives\\AudioPlayer\\Metadata.php":2740472464,"src\\Response\\Directives\\AudioPlayer\\PlayDirective.php":1520928509,"src\\Response\\Directives\\AudioPlayer\\StopDirective.php":2966754291,"src\\Response\\Directives\\AudioPlayer\\Stream.php":639800167,"src\\Response\\Directives\\Dialog\\ConfirmIntentDirective.php":4058205418,"src\\Response\\Directives\\Dialog\\ConfirmSlotDirective.php":2335457304,"src\\Response\\Directives\\Dialog\\DelegateDirective.php":3966013697,"src\\Response\\Directives\\Dialog\\ElicitSlotDirective.php":2461952060,"src\\Response\\Directives\\Dialog\\Entity\\Type.php":2747388625,"src\\Response\\Directives\\Dialog\\Entity\\TypeValue.php":1689797411,"src\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\Clear.php":4232465519,"src\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\Replace.php":755462223,"src\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\UpdateDynamicEntities.php":1894088646,"src\\Response\\Directives\\Directive.php":1592726405,"src\\Response\\Directives\\Display\\HintDirective.php":2693342369,"src\\Response\\Directives\\Display\\Image.php":1232227111,"src\\Response\\Directives\\Display\\ImageSource.php":652709536,"src\\Response\\Directives\\Display\\ListItem.php":997872452,"src\\Response\\Directives\\Display\\RenderTemplateDirective.php":3080645407,"src\\Response\\Directives\\Display\\Template.php":2099925875,"src\\Response\\Directives\\Display\\Text.php":859276084,"src\\Response\\Directives\\Display\\TextContent.php":1986440717,"src\\Response\\Directives\\GadgetController\\Animation.php":4294905055,"src\\Response\\Directives\\GadgetController\\Parameters.php":1548165964,"src\\Response\\Directives\\GadgetController\\Sequence.php":92034664,"src\\Response\\Directives\\GadgetController\\SetLightDirective.php":1984970304,"src\\Response\\Directives\\GameEngine\\Event.php":2682287203,"src\\Response\\Directives\\GameEngine\\Pattern.php":3820074374,"src\\Response\\Directives\\GameEngine\\Recognizer.php":939234115,"src\\Response\\Directives\\GameEngine\\RecognizerDeviation.php":3343269280,"src\\Response\\Directives\\GameEngine\\RecognizerMatch.php":3152506201,"src\\Response\\Directives\\GameEngine\\RecognizerProgress.php":4195199327,"src\\Response\\Directives\\GameEngine\\StartInputHandlerDirective.php":1777910291,"src\\Response\\Directives\\GameEngine\\StopInputHandlerDirective.php":1938138406,"src\\Response\\Directives\\VideoApp\\Metadata.php":1801430675,"src\\Response\\Directives\\VideoApp\\VideoItem.php":1559970762,"src\\Response\\Directives\\VideoApp\\VideoLaunchDirective.php":328210989,"src\\Response\\OutputSpeech.php":1165108567,"src\\Response\\Reprompt.php":3853205103,"src\\Response\\Response.php":1888944070,"src\\Response\\ResponseBody.php":1366401768,"src\\Response\\ResponseBodyInterface.php":2740385681,"src\\Validation\\RequestValidator.php":1466899394,"test\\bootstrap.php":3824695673,"test\\Test\\Helper\\DeviceAddressInformationHelperTest.php":2259469043,"test\\Test\\Helper\\SsmlGeneratorTest.php":3557088786,"test\\Test\\Intent\\IntentTest.php":170262575,"test\\Test\\Intent\\SlotTest.php":709193813,"test\\Test\\Request\\AlexaSkillEventRequestsTest.php":1605900274,"test\\Test\\Request\\AudioPlayerRequestsTest.php":2780453986,"test\\Test\\Request\\CanFulfillIntentRequestTest.php":4256547526,"test\\Test\\Request\\ConnectionsResponseRequestTest.php":3661891738,"test\\Test\\Request\\ElementSelectedRequestTest.php":1139368572,"test\\Test\\Request\\ExceptionEncounteredRequestTest.php":2903502475,"test\\Test\\Request\\GeolocationRequestTest.php":2808774422,"test\\Test\\Request\\InputHandlerEventTest.php":91911846,"test\\Test\\Request\\IntentRequestTest.php":3977957265,"test\\Test\\Request\\LaunchRequestTest.php":3940451363,"test\\Test\\Request\\PlaybackControllerRequestsTest.php":1676902823,"test\\Test\\Request\\SessionEndedRequestTest.php":2064713156,"test\\Test\\RequestHandler\\Basic\\CancelRequestHandlerTest.php":901439760,"test\\Test\\RequestHandler\\Basic\\ExceptionEncounteredRequestHandlerTest.php":95117629,"test\\Test\\RequestHandler\\Basic\\HelpRequestHandlerTest.php":1621131837,"test\\Test\\RequestHandler\\Basic\\NavigateHomeRequestHandlerTest.php":683626607,"test\\Test\\RequestHandler\\Basic\\SessionEndedRequestHandlerTest.php":3758628178,"test\\Test\\RequestHandler\\Basic\\StopRequestHandlerTest.php":3762841434,"test\\Test\\RequestHandler\\RequestHandlerRegistryTest.php":1685470781,"test\\Test\\Response\\CanFulfillResponseBodyTest.php":155901049,"test\\Test\\Response\\CardTest.php":992476029,"test\\Test\\Response\\Directives\\AudioTest.php":798979897,"test\\Test\\Response\\Directives\\Dialog\\ConfirmIntentDirectiveTest.php":4154066969,"test\\Test\\Response\\Directives\\Dialog\\ConfirmSlotDirectiveTest.php":353128182,"test\\Test\\Response\\Directives\\Dialog\\DelegateDirectiveTest.php":1919014869,"test\\Test\\Response\\Directives\\Dialog\\ElicitSlotDirectiveTest.php":1010128102,"test\\Test\\Response\\Directives\\Dialog\\Entity\\TypeTest.php":3309274736,"test\\Test\\Response\\Directives\\Dialog\\Entity\\TypeValueTest.php":1138012484,"test\\Test\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\ClearTest.php":66355570,"test\\Test\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\ReplaceTest.php":1096567243,"test\\Test\\Response\\Directives\\Display\\TemplateTest.php":3304275105,"test\\Test\\Response\\Directives\\Display\\TextContentTest.php":2489267604,"test\\Test\\Response\\Directives\\DisplayTest.php":2139905703,"test\\Test\\Response\\Directives\\GadgetControllerTest.php":3709933278,"test\\Test\\Response\\Directives\\GameEngineTest.php":3226075983,"test\\Test\\Response\\Directives\\VideoAppTest.php":2050197866,"test\\Test\\Response\\ResponseBodyTest.php":4202457093,"test\\Test\\Response\\ResponseHelperTest.php":1819916683,"test\\Test\\Response\\ResponseTest.php":3986905089,"test\\Test\\Validation\\RequestValidatorTest.php":3687971773}} \ No newline at end of file +{"php":"8.1.5","version":"3.9.6-DEV:dev-master#22804e82950a7d80f1185872c8396fca1c675f45","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"align_single_space"},"blank_line_after_namespace":true,"blank_line_after_opening_tag":true,"blank_line_before_statement":{"statements":["return"]},"braces":true,"cast_spaces":true,"class_definition":true,"concat_space":true,"declare_equal_normalize":true,"elseif":true,"encoding":true,"no_extra_blank_lines":true,"full_opening_tag":true,"function_declaration":true,"function_typehint_space":true,"heredoc_to_nowdoc":true,"include":true,"indentation_type":true,"line_ending":true,"lowercase_cast":true,"single_line_comment_style":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ensure_fully_multiline"},"multiline_whitespace_before_semicolons":true,"native_function_casing":true,"new_with_braces":true,"linebreak_after_opening_tag":true,"no_alias_functions":true,"no_blank_lines_after_class_opening":true,"no_blank_lines_after_phpdoc":true,"no_closing_tag":true,"no_empty_comment":true,"no_empty_phpdoc":true,"no_empty_statement":true,"no_leading_import_slash":true,"no_leading_namespace_whitespace":true,"no_mixed_echo_print":true,"no_multiline_whitespace_around_double_arrow":true,"no_short_bool_cast":true,"no_singleline_whitespace_before_semicolons":true,"no_spaces_after_function_name":true,"no_spaces_around_offset":true,"no_spaces_inside_parenthesis":true,"no_trailing_comma_in_list_call":true,"no_trailing_comma_in_singleline_array":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"no_unneeded_control_parentheses":true,"no_unreachable_default_argument_value":true,"no_unused_imports":true,"no_useless_else":true,"no_useless_return":true,"no_whitespace_before_comma_in_array":true,"no_whitespace_in_blank_line":true,"normalize_index_brace":true,"object_operator_without_whitespace":true,"ordered_imports":true,"php_unit_construct":true,"php_unit_dedicate_assert":true,"php_unit_fqcn_annotation":true,"phpdoc_add_missing_param_annotation":true,"phpdoc_align":true,"phpdoc_annotation_without_dot":true,"phpdoc_indent":true,"general_phpdoc_tag_rename":true,"phpdoc_inline_tag_normalizer":true,"phpdoc_tag_type":true,"phpdoc_no_access":true,"phpdoc_no_empty_return":true,"phpdoc_no_package":true,"phpdoc_order":true,"phpdoc_scalar":true,"phpdoc_separation":true,"phpdoc_single_line_var_spacing":true,"phpdoc_summary":true,"phpdoc_to_comment":true,"phpdoc_trim":true,"phpdoc_no_alias_tag":true,"phpdoc_types":true,"phpdoc_var_without_name":true,"pow_to_exponentiation":true,"increment_style":{"style":"pre"},"psr_autoloading":true,"random_api_migration":true,"return_type_declaration":true,"self_accessor":true,"semicolon_after_instruction":true,"array_syntax":{"syntax":"short"},"short_scalar_cast":true,"error_suppression":true,"single_blank_line_at_eof":true,"single_blank_line_before_namespace":true,"single_class_element_per_statement":{"elements":["property"]},"single_import_per_statement":true,"single_line_after_imports":true,"single_quote":true,"space_after_semicolon":true,"standardize_not_equals":true,"strict_comparison":true,"strict_param":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"ternary_operator_spaces":true,"trailing_comma_in_multiline":{"elements":["arrays"]},"trim_array_spaces":true,"unary_operator_spaces":true,"visibility_required":{"elements":["method","property"]},"whitespace_after_comma_in_array":true,"constant_case":true,"no_break_comment":true,"no_space_around_double_colon":true},"hashes":{"src\\Exception\\DeviceApiCallException.php":397307940,"src\\Exception\\InvalidCardPermissionsException.php":3194439575,"src\\Exception\\InvalidSsmlException.php":274108870,"src\\Exception\\MissingRequestDataException.php":489670375,"src\\Exception\\MissingRequestHandlerException.php":2510768499,"src\\Exception\\MissingRequiredHeaderException.php":3635596926,"src\\Exception\\OutdatedCertExceptionException.php":2732495116,"src\\Exception\\RequestInvalidSignatureException.php":3596342060,"src\\Exception\\RequestInvalidTimestampException.php":2346064383,"src\\Helper\\ResponseHelper.php":3687729275,"src\\Helper\\SsmlGenerator.php":1288062931,"src\\Helper\\SsmlTypes.php":954324338,"src\\Intent\\Intent.php":767475374,"src\\Intent\\IntentStatus.php":653912920,"src\\Intent\\IntentValue.php":1530434202,"src\\Intent\\Resolution.php":724455019,"src\\Intent\\Slot.php":1998609919,"src\\Request\\Altitude.php":4272229216,"src\\Request\\Context.php":3142905282,"src\\Request\\Coordinate.php":1555575182,"src\\Request\\Geolocation.php":3293137606,"src\\Request\\Heading.php":2684314193,"src\\Request\\LocationServices.php":1012151918,"src\\Request\\Request\\AbstractRequest.php":1863190066,"src\\Request\\Request\\AlexaSkillEvent\\AlexaSkillEventRequest.php":1595930221,"src\\Request\\Request\\AlexaSkillEvent\\SkillAccountLinkedRequest.php":762195851,"src\\Request\\Request\\AlexaSkillEvent\\SkillDisabledRequest.php":4133461499,"src\\Request\\Request\\AlexaSkillEvent\\SkillEnabledRequest.php":3393486954,"src\\Request\\Request\\AlexaSkillEvent\\SkillPermissionAcceptedRequest.php":22183186,"src\\Request\\Request\\AlexaSkillEvent\\SkillPermissionBody.php":2058528688,"src\\Request\\Request\\AlexaSkillEvent\\SkillPermissionChangedRequest.php":1830336513,"src\\Request\\Request\\AudioPlayer\\PlaybackFailedRequest.php":1518761903,"src\\Request\\Request\\CanFulfill\\CanFulfillIntentRequest.php":3659921764,"src\\Request\\Request\\Display\\ElementSelectedRequest.php":1321680358,"src\\Request\\Request\\Error.php":639069852,"src\\Request\\Request\\GameEngine\\Event\\Event.php":1832495237,"src\\Request\\Request\\GameEngine\\Event\\InputEvent.php":3897164627,"src\\Request\\Request\\GameEngine\\InputHandlerEvent.php":3895611239,"src\\Request\\Request\\PlaybackController\\AbstractPlaybackController.php":1036205313,"src\\Request\\Request\\PlaybackController\\NextCommandIssued.php":3192103095,"src\\Request\\Request\\PlaybackController\\PauseCommandIssued.php":1592392333,"src\\Request\\Request\\PlaybackController\\PlayCommandIssued.php":1675200176,"src\\Request\\Request\\PlaybackController\\PreviousCommandIssued.php":563877389,"src\\Request\\Request\\Standard\\LaunchRequest.php":1376844276,"src\\Request\\Request\\Standard\\StandardRequest.php":106014074,"src\\Request\\Request\\System\\ExceptionEncounteredRequest.php":3022964728,"src\\Request\\Request\\System\\SystemRequest.php":749011239,"src\\Request\\Speed.php":1695802154,"src\\RequestHandler\\AbstractRequestHandler.php":832848863,"src\\RequestHandler\\Basic\\CancelRequestHandler.php":442988638,"src\\RequestHandler\\Basic\\ExceptionEncounteredRequestHandler.php":3607095168,"src\\RequestHandler\\Basic\\HelpRequestHandler.php":2436916006,"src\\RequestHandler\\Basic\\NavigateHomeRequestHandler.php":2260083906,"src\\RequestHandler\\Basic\\SessionEndedRequestHandler.php":2730579585,"src\\RequestHandler\\Basic\\StopRequestHandler.php":3796312275,"src\\RequestHandler\\RequestHandlerRegistry.php":938829433,"src\\Response\\CanFulfill\\CanFulfillIntentResponse.php":11474660,"src\\Response\\CanFulfill\\CanFulfillResponseBody.php":357970446,"src\\Response\\CanFulfill\\CanFulfillSlot.php":168508376,"src\\Response\\CardImage.php":2488769290,"src\\Response\\Directives\\AudioPlayer\\AudioItem.php":260504635,"src\\Response\\Directives\\AudioPlayer\\ClearDirective.php":3467354814,"src\\Response\\Directives\\AudioPlayer\\Metadata.php":2740472464,"src\\Response\\Directives\\AudioPlayer\\PlayDirective.php":1520928509,"src\\Response\\Directives\\AudioPlayer\\StopDirective.php":2966754291,"src\\Response\\Directives\\AudioPlayer\\Stream.php":639800167,"src\\Response\\Directives\\Dialog\\ConfirmIntentDirective.php":4058205418,"src\\Response\\Directives\\Dialog\\ConfirmSlotDirective.php":2335457304,"src\\Response\\Directives\\Dialog\\DelegateDirective.php":3966013697,"src\\Response\\Directives\\Dialog\\ElicitSlotDirective.php":2461952060,"src\\Response\\Directives\\Dialog\\Entity\\Type.php":2747388625,"src\\Response\\Directives\\Dialog\\Entity\\TypeValue.php":1689797411,"src\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\Clear.php":4232465519,"src\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\Replace.php":755462223,"src\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\UpdateDynamicEntities.php":1894088646,"src\\Response\\Directives\\Directive.php":1592726405,"src\\Response\\Directives\\Display\\HintDirective.php":2693342369,"src\\Response\\Directives\\Display\\Image.php":1232227111,"src\\Response\\Directives\\Display\\ListItem.php":997872452,"src\\Response\\Directives\\Display\\RenderTemplateDirective.php":3080645407,"src\\Response\\Directives\\Display\\Text.php":859276084,"src\\Response\\Directives\\GadgetController\\Animation.php":4294905055,"src\\Response\\Directives\\GadgetController\\Parameters.php":1548165964,"src\\Response\\Directives\\GadgetController\\Sequence.php":92034664,"src\\Response\\Directives\\GadgetController\\SetLightDirective.php":1984970304,"src\\Response\\Directives\\GameEngine\\Event.php":2682287203,"src\\Response\\Directives\\GameEngine\\Pattern.php":3820074374,"src\\Response\\Directives\\GameEngine\\Recognizer.php":939234115,"src\\Response\\Directives\\GameEngine\\RecognizerDeviation.php":3343269280,"src\\Response\\Directives\\GameEngine\\RecognizerMatch.php":3152506201,"src\\Response\\Directives\\GameEngine\\RecognizerProgress.php":4195199327,"src\\Response\\Directives\\GameEngine\\StartInputHandlerDirective.php":1777910291,"src\\Response\\Directives\\GameEngine\\StopInputHandlerDirective.php":1938138406,"src\\Response\\Directives\\VideoApp\\Metadata.php":1801430675,"src\\Response\\Directives\\VideoApp\\VideoItem.php":1559970762,"src\\Response\\Directives\\VideoApp\\VideoLaunchDirective.php":328210989,"src\\Response\\OutputSpeech.php":1165108567,"src\\Response\\Reprompt.php":3853205103,"src\\Response\\Response.php":1888944070,"src\\Response\\ResponseBodyInterface.php":2740385681,"test\\bootstrap.php":3824695673,"test\\Test\\Helper\\DeviceAddressInformationHelperTest.php":2259469043,"test\\Test\\Helper\\SsmlGeneratorTest.php":3557088786,"test\\Test\\Intent\\IntentTest.php":170262575,"test\\Test\\Intent\\SlotTest.php":709193813,"test\\Test\\Request\\AlexaSkillEventRequestsTest.php":1605900274,"test\\Test\\Request\\AudioPlayerRequestsTest.php":2780453986,"test\\Test\\Request\\CanFulfillIntentRequestTest.php":4256547526,"test\\Test\\Request\\ConnectionsResponseRequestTest.php":3661891738,"test\\Test\\Request\\ElementSelectedRequestTest.php":1139368572,"test\\Test\\Request\\ExceptionEncounteredRequestTest.php":2903502475,"test\\Test\\Request\\GeolocationRequestTest.php":2808774422,"test\\Test\\Request\\InputHandlerEventTest.php":91911846,"test\\Test\\Request\\IntentRequestTest.php":3977957265,"test\\Test\\Request\\LaunchRequestTest.php":3940451363,"test\\Test\\Request\\PlaybackControllerRequestsTest.php":1676902823,"test\\Test\\Request\\SessionEndedRequestTest.php":2064713156,"test\\Test\\RequestHandler\\Basic\\CancelRequestHandlerTest.php":901439760,"test\\Test\\RequestHandler\\Basic\\ExceptionEncounteredRequestHandlerTest.php":95117629,"test\\Test\\RequestHandler\\Basic\\HelpRequestHandlerTest.php":1621131837,"test\\Test\\RequestHandler\\Basic\\NavigateHomeRequestHandlerTest.php":683626607,"test\\Test\\RequestHandler\\Basic\\SessionEndedRequestHandlerTest.php":3758628178,"test\\Test\\RequestHandler\\Basic\\StopRequestHandlerTest.php":3762841434,"test\\Test\\RequestHandler\\RequestHandlerRegistryTest.php":1685470781,"test\\Test\\Response\\CanFulfillResponseBodyTest.php":155901049,"test\\Test\\Response\\CardTest.php":992476029,"test\\Test\\Response\\Directives\\AudioTest.php":798979897,"test\\Test\\Response\\Directives\\Dialog\\ConfirmIntentDirectiveTest.php":4154066969,"test\\Test\\Response\\Directives\\Dialog\\ConfirmSlotDirectiveTest.php":353128182,"test\\Test\\Response\\Directives\\Dialog\\DelegateDirectiveTest.php":1919014869,"test\\Test\\Response\\Directives\\Dialog\\ElicitSlotDirectiveTest.php":1010128102,"test\\Test\\Response\\Directives\\Dialog\\Entity\\TypeTest.php":3309274736,"test\\Test\\Response\\Directives\\Dialog\\Entity\\TypeValueTest.php":1138012484,"test\\Test\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\ClearTest.php":66355570,"test\\Test\\Response\\Directives\\Dialog\\UpdateDynamicEntities\\ReplaceTest.php":1096567243,"test\\Test\\Response\\Directives\\Display\\TemplateTest.php":3304275105,"test\\Test\\Response\\Directives\\Display\\TextContentTest.php":2489267604,"test\\Test\\Response\\Directives\\DisplayTest.php":2139905703,"test\\Test\\Response\\Directives\\GadgetControllerTest.php":3709933278,"test\\Test\\Response\\Directives\\GameEngineTest.php":3226075983,"test\\Test\\Response\\Directives\\VideoAppTest.php":2050197866,"test\\Test\\Response\\ResponseBodyTest.php":4202457093,"test\\Test\\Response\\ResponseHelperTest.php":1819916683,"test\\Test\\Response\\ResponseTest.php":3986905089,"test\\Test\\Validation\\RequestValidatorTest.php":3687971773,"src\\Helper\\PropertyHelper.php":372531033,"test\\Test\\Helper\\PropertyHelperTest.php":3508448179,"src\\Request\\Application.php":3645664373,"src\\Request\\AudioPlayer.php":2514737281,"src\\Request\\Device\\DeviceAddressInformation.php":3057448936,"src\\Request\\Device.php":1318277956,"src\\Request\\Request\\AlexaSkillEvent\\Permission.php":847805178,"src\\Request\\Request\\AlexaSkillEvent\\SkillAccountLinkedBody.php":1177445068,"src\\Request\\Request\\AlexaSkillEvent\\SkillDisabledBody.php":2094152520,"src\\Request\\Request\\AudioPlayer\\AudioPlayerRequest.php":3555194724,"src\\Request\\Request\\AudioPlayer\\PlaybackFinishedRequest.php":1413531210,"src\\Request\\Request\\AudioPlayer\\PlaybackNearlyFinishedRequest.php":1730653853,"src\\Request\\Request\\AudioPlayer\\PlaybackStartedRequest.php":565532923,"src\\Request\\Request\\AudioPlayer\\PlaybackState.php":1892808062,"src\\Request\\Request\\AudioPlayer\\PlaybackStoppedRequest.php":3072973997,"src\\Request\\Request\\Standard\\IntentRequest.php":1076807148,"src\\Request\\Request\\Standard\\SessionEndedRequest.php":2090980707,"src\\Request\\Request\\System\\Cause.php":4133107586,"src\\Request\\Request\\System\\ConnectionsResponseRequest.php":1476075891,"src\\Request\\Request\\System\\Payload.php":515244270,"src\\Request\\Request\\System\\Status.php":3084005054,"src\\Request\\Session.php":3784931181,"src\\Request\\System.php":2460013830,"src\\Request\\User.php":1717156385,"src\\Request\\UserPermissions.php":2395520139,"src\\Response\\Card.php":3592783613,"src\\Response\\Directives\\Display\\ImageSource.php":2663837381,"src\\Response\\Directives\\Display\\Template.php":2764542017,"src\\Response\\Directives\\Display\\TextContent.php":2832656449,"src\\Response\\ResponseBody.php":2295250930,"src\\Helper\\DeviceAddressInformationHelper.php":349251089,"src\\Helper\\SerializeValueMapper.php":1277694272,"src\\Validation\\RequestValidator.php":1858584113,"src\\Request\\Request.php":3577517432}} \ No newline at end of file diff --git a/src/Helper/DeviceAddressInformationHelper.php b/src/Helper/DeviceAddressInformationHelper.php index f92b729..bfa1b88 100644 --- a/src/Helper/DeviceAddressInformationHelper.php +++ b/src/Helper/DeviceAddressInformationHelper.php @@ -92,23 +92,15 @@ private function apiCall(string $url, string $token): DeviceAddressInformation /* * Api Call response codes: - * 200 OK Successfully got the address associated with this deviceId. - * 204 No Content The query did not return any results. + * 200 OK Successfully got the address associated with this deviceId. + * 204 No Content The query did not return any results. * 403 Forbidden The authentication token is invalid or doesn’t have access to the resource. - * 405 Method Not Allowed The method is not supported. + * 405 Method Not Allowed The method is not supported. * 429 Too Many Requests The skill has been throttled due to an excessive number of requests. - * 500 Internal Error An unexpected error occurred. + * 500 Internal Error An unexpected error occurred. */ - switch ($response->getStatusCode()) { - case 200: - break; - case 204: - case 403: - case 405: - case 429: - case 500: - default: - throw new DeviceApiCallException(sprintf('Error in api call (status code:"%s")', $response->getStatusCode())); + if (200 !== $response->getStatusCode()) { + throw new DeviceApiCallException(sprintf('Error in api call (status code:"%s")', $response->getStatusCode())); } return DeviceAddressInformation::fromApiResponse(json_decode($response->getBody()->getContents(), true)); diff --git a/src/Helper/PropertyHelper.php b/src/Helper/PropertyHelper.php new file mode 100644 index 0000000..661c1ab --- /dev/null +++ b/src/Helper/PropertyHelper.php @@ -0,0 +1,33 @@ + + */ +class PropertyHelper +{ + /** + * @param array $data + * @param string $key + * + * @return string|null + */ + public static function checkNullValueString(array $data, string $key) + { + return isset($data[$key]) ? $data[$key] : null; + } + + /** + * @param array $data + * @param string $key + * + * @return int|null + */ + public static function checkNullValueInt(array $data, string $key) + { + return isset($data[$key]) ? $data[$key] : null; + } +} diff --git a/src/Helper/SerializeValueMapper.php b/src/Helper/SerializeValueMapper.php new file mode 100644 index 0000000..6186f07 --- /dev/null +++ b/src/Helper/SerializeValueMapper.php @@ -0,0 +1,22 @@ + + */ +trait SerializeValueMapper +{ + /** + * @param \ArrayObject $data + * @param string $property + */ + protected function valueToArrayIfSet(\ArrayObject $data, string $property) + { + if (null !== $this->{$property}) { + $data[$property] = $this->{$property}; + } + } +} diff --git a/src/Request/Application.php b/src/Request/Application.php index 0a3b264..fc7cfee 100644 --- a/src/Request/Application.php +++ b/src/Request/Application.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * Represents the current Skill. * @@ -23,7 +25,7 @@ public static function fromAmazonRequest(array $amazonRequest): self { $application = new self(); - $application->applicationId = isset($amazonRequest['applicationId']) ? $amazonRequest['applicationId'] : null; + $application->applicationId = PropertyHelper::checkNullValueString($amazonRequest, 'applicationId'); return $application; } diff --git a/src/Request/AudioPlayer.php b/src/Request/AudioPlayer.php index 669ce1f..405d418 100644 --- a/src/Request/AudioPlayer.php +++ b/src/Request/AudioPlayer.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -38,9 +40,9 @@ public static function fromAmazonRequest(array $amazonRequest): self { $audioPlayer = new self(); - $audioPlayer->token = isset($amazonRequest['token']) ? $amazonRequest['token'] : null; - $audioPlayer->offsetInMilliseconds = isset($amazonRequest['offsetInMilliseconds']) ? (int) $amazonRequest['offsetInMilliseconds'] : null; - $audioPlayer->playerActivity = isset($amazonRequest['playerActivity']) ? $amazonRequest['playerActivity'] : null; + $audioPlayer->token = PropertyHelper::checkNullValueString($amazonRequest, 'token'); + $audioPlayer->offsetInMilliseconds = PropertyHelper::checkNullValueInt($amazonRequest, 'offsetInMilliseconds'); + $audioPlayer->playerActivity = PropertyHelper::checkNullValueString($amazonRequest, 'playerActivity'); return $audioPlayer; } diff --git a/src/Request/Device.php b/src/Request/Device.php index 0421ee2..754e39e 100644 --- a/src/Request/Device.php +++ b/src/Request/Device.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -31,9 +33,9 @@ public static function fromAmazonRequest(array $amazonRequest): self { $device = new self(); - $device->deviceId = isset($amazonRequest['deviceId']) ? $amazonRequest['deviceId'] : null; + $device->deviceId = PropertyHelper::checkNullValueString($amazonRequest, 'deviceId'); $device->supportedInterfaces = isset($amazonRequest['supportedInterfaces']) ? (array) $amazonRequest['supportedInterfaces'] : []; - $device->accessToken = isset($amazonRequest['accessToken']) ? $amazonRequest['accessToken'] : null; + $device->accessToken = PropertyHelper::checkNullValueString($amazonRequest, 'accessToken'); return $device; } diff --git a/src/Request/Device/DeviceAddressInformation.php b/src/Request/Device/DeviceAddressInformation.php index 0670a51..9c86d12 100644 --- a/src/Request/Device/DeviceAddressInformation.php +++ b/src/Request/Device/DeviceAddressInformation.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request\Device; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -56,14 +58,14 @@ public static function fromApiResponse(array $amazonApiResponse): self { $deviceAddressInformation = new self(); - $deviceAddressInformation->stateOrRegion = isset($amazonApiResponse['stateOrRegion']) ? $amazonApiResponse['stateOrRegion'] : null; - $deviceAddressInformation->city = isset($amazonApiResponse['city']) ? $amazonApiResponse['city'] : null; - $deviceAddressInformation->countryCode = isset($amazonApiResponse['countryCode']) ? $amazonApiResponse['countryCode'] : null; - $deviceAddressInformation->postalCode = isset($amazonApiResponse['postalCode']) ? $amazonApiResponse['postalCode'] : null; - $deviceAddressInformation->addressLine1 = isset($amazonApiResponse['addressLine1']) ? $amazonApiResponse['addressLine1'] : null; - $deviceAddressInformation->addressLine2 = isset($amazonApiResponse['addressLine2']) ? $amazonApiResponse['addressLine2'] : null; - $deviceAddressInformation->addressLine3 = isset($amazonApiResponse['addressLine3']) ? $amazonApiResponse['addressLine3'] : null; - $deviceAddressInformation->districtOrCounty = isset($amazonApiResponse['districtOrCounty']) ? $amazonApiResponse['districtOrCounty'] : null; + $deviceAddressInformation->stateOrRegion = PropertyHelper::checkNullValueString($amazonApiResponse, 'stateOrRegion'); + $deviceAddressInformation->city = PropertyHelper::checkNullValueString($amazonApiResponse, 'city'); + $deviceAddressInformation->countryCode = PropertyHelper::checkNullValueString($amazonApiResponse, 'countryCode'); + $deviceAddressInformation->postalCode = PropertyHelper::checkNullValueString($amazonApiResponse, 'postalCode'); + $deviceAddressInformation->addressLine1 = PropertyHelper::checkNullValueString($amazonApiResponse, 'addressLine1'); + $deviceAddressInformation->addressLine2 = PropertyHelper::checkNullValueString($amazonApiResponse, 'addressLine2'); + $deviceAddressInformation->addressLine3 = PropertyHelper::checkNullValueString($amazonApiResponse, 'addressLine3'); + $deviceAddressInformation->districtOrCounty = PropertyHelper::checkNullValueString($amazonApiResponse, 'districtOrCounty'); return $deviceAddressInformation; } diff --git a/src/Request/Request.php b/src/Request/Request.php index 3b5b551..fe5ebfd 100644 --- a/src/Request/Request.php +++ b/src/Request/Request.php @@ -4,6 +4,7 @@ use MaxBeckers\AmazonAlexa\Exception\MissingRequestDataException; use MaxBeckers\AmazonAlexa\Exception\MissingRequiredHeaderException; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; use MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest; use MaxBeckers\AmazonAlexa\Request\Request\AlexaSkillEvent\SkillAccountLinkedRequest; use MaxBeckers\AmazonAlexa\Request\Request\AlexaSkillEvent\SkillDisabledRequest; @@ -38,30 +39,30 @@ class Request */ const REQUEST_TYPES = [ // Standard types - IntentRequest::TYPE => IntentRequest::class, - LaunchRequest::TYPE => LaunchRequest::class, - SessionEndedRequest::TYPE => SessionEndedRequest::class, + IntentRequest::TYPE => IntentRequest::class, + LaunchRequest::TYPE => LaunchRequest::class, + SessionEndedRequest::TYPE => SessionEndedRequest::class, // AudioPlayer types - PlaybackStartedRequest::TYPE => PlaybackStartedRequest::class, - PlaybackNearlyFinishedRequest::TYPE => PlaybackNearlyFinishedRequest::class, - PlaybackFinishedRequest::TYPE => PlaybackFinishedRequest::class, - PlaybackStoppedRequest::TYPE => PlaybackStoppedRequest::class, - PlaybackFailedRequest::TYPE => PlaybackFailedRequest::class, + PlaybackStartedRequest::TYPE => PlaybackStartedRequest::class, + PlaybackNearlyFinishedRequest::TYPE => PlaybackNearlyFinishedRequest::class, + PlaybackFinishedRequest::TYPE => PlaybackFinishedRequest::class, + PlaybackStoppedRequest::TYPE => PlaybackStoppedRequest::class, + PlaybackFailedRequest::TYPE => PlaybackFailedRequest::class, // PlaybackController types - NextCommandIssued::TYPE => NextCommandIssued::class, - PauseCommandIssued::TYPE => PauseCommandIssued::class, - PlayCommandIssued::TYPE => PlayCommandIssued::class, - PreviousCommandIssued::TYPE => PreviousCommandIssued::class, + NextCommandIssued::TYPE => NextCommandIssued::class, + PauseCommandIssued::TYPE => PauseCommandIssued::class, + PlayCommandIssued::TYPE => PlayCommandIssued::class, + PreviousCommandIssued::TYPE => PreviousCommandIssued::class, // System types - ExceptionEncounteredRequest::TYPE => ExceptionEncounteredRequest::class, + ExceptionEncounteredRequest::TYPE => ExceptionEncounteredRequest::class, // Display types - ElementSelectedRequest::TYPE => ElementSelectedRequest::class, + ElementSelectedRequest::TYPE => ElementSelectedRequest::class, // Game engine types - InputHandlerEvent::TYPE => InputHandlerEvent::class, + InputHandlerEvent::TYPE => InputHandlerEvent::class, // can fulfill intent - CanFulfillIntentRequest::TYPE => CanFulfillIntentRequest::class, + CanFulfillIntentRequest::TYPE => CanFulfillIntentRequest::class, // Connections Response Request - ConnectionsResponseRequest::TYPE => ConnectionsResponseRequest::class, + ConnectionsResponseRequest::TYPE => ConnectionsResponseRequest::class, // Skill event types SkillAccountLinkedRequest::TYPE => SkillAccountLinkedRequest::class, SkillEnabledRequest::TYPE => SkillEnabledRequest::class, @@ -110,8 +111,8 @@ class Request * @param string $signatureCertChainUrl * @param string $signature * - * @throws MissingRequestDataException * @throws MissingRequiredHeaderException + * @throws MissingRequestDataException * * @return Request */ @@ -122,23 +123,14 @@ public static function fromAmazonRequest(string $amazonRequestBody, string $sign $request->signatureCertChainUrl = $signatureCertChainUrl; $request->signature = $signature; $request->amazonRequestBody = $amazonRequestBody; - $amazonRequest = json_decode($amazonRequestBody, true); + $amazonRequest = (array) json_decode($amazonRequestBody, true); - $request->version = isset($amazonRequest['version']) ? $amazonRequest['version'] : null; + $request->version = PropertyHelper::checkNullValueString($amazonRequest, 'version'); $request->session = isset($amazonRequest['session']) ? Session::fromAmazonRequest($amazonRequest['session']) : null; $request->context = isset($amazonRequest['context']) ? Context::fromAmazonRequest($amazonRequest['context']) : null; - if (isset($amazonRequest['request']['type']) && isset(self::REQUEST_TYPES[$amazonRequest['request']['type']])) { - $request->request = (self::REQUEST_TYPES[$amazonRequest['request']['type']])::fromAmazonRequest($amazonRequest['request']); - } else { - throw new MissingRequestDataException(); - } - - if ($request->request->validateSignature()) { - if (!$request->signatureCertChainUrl || !$request->signature) { - throw new MissingRequiredHeaderException(); - } - } + $request->setRequest($amazonRequest); + $request->checkSignature(); return $request; } @@ -157,4 +149,27 @@ public function getApplicationId() return null; } + + /** + * @param array $amazonRequest + * + * @throws MissingRequestDataException + */ + private function setRequest(array $amazonRequest) + { + if (!isset($amazonRequest['request']['type']) || !isset(self::REQUEST_TYPES[$amazonRequest['request']['type']])) { + throw new MissingRequestDataException(); + } + $this->request = (self::REQUEST_TYPES[$amazonRequest['request']['type']])::fromAmazonRequest($amazonRequest['request']); + } + + /** + * @throws MissingRequiredHeaderException + */ + private function checkSignature() + { + if ($this->request->validateSignature() && (!$this->signatureCertChainUrl || !$this->signature)) { + throw new MissingRequiredHeaderException(); + } + } } diff --git a/src/Request/Request/AlexaSkillEvent/Permission.php b/src/Request/Request/AlexaSkillEvent/Permission.php index 8daa23a..653d1c4 100644 --- a/src/Request/Request/AlexaSkillEvent/Permission.php +++ b/src/Request/Request/AlexaSkillEvent/Permission.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\AlexaSkillEvent; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -21,7 +23,7 @@ public static function fromAmazonRequest(array $amazonRequest): self { $permission = new self(); - $permission->scope = isset($amazonRequest['scope']) ? $amazonRequest['scope'] : null; + $permission->scope = PropertyHelper::checkNullValueString($amazonRequest, 'scope'); return $permission; } diff --git a/src/Request/Request/AlexaSkillEvent/SkillAccountLinkedBody.php b/src/Request/Request/AlexaSkillEvent/SkillAccountLinkedBody.php index fd48208..957c84e 100644 --- a/src/Request/Request/AlexaSkillEvent/SkillAccountLinkedBody.php +++ b/src/Request/Request/AlexaSkillEvent/SkillAccountLinkedBody.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\AlexaSkillEvent; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -21,7 +23,7 @@ public static function fromAmazonRequest(array $amazonRequest): self { $body = new self(); - $body->accessToken = isset($amazonRequest['accessToken']) ? $amazonRequest['accessToken'] : null; + $body->accessToken = PropertyHelper::checkNullValueString($amazonRequest, 'accessToken'); return $body; } diff --git a/src/Request/Request/AlexaSkillEvent/SkillDisabledBody.php b/src/Request/Request/AlexaSkillEvent/SkillDisabledBody.php index b1e61f4..b3e4ff5 100644 --- a/src/Request/Request/AlexaSkillEvent/SkillDisabledBody.php +++ b/src/Request/Request/AlexaSkillEvent/SkillDisabledBody.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\AlexaSkillEvent; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -24,7 +26,7 @@ public static function fromAmazonRequest(array $amazonRequest): self { $body = new self(); - $body->userInformationPersistenceStatus = isset($amazonRequest['userInformationPersistenceStatus']) ? $amazonRequest['userInformationPersistenceStatus'] : null; + $body->userInformationPersistenceStatus = PropertyHelper::checkNullValueString($amazonRequest, 'userInformationPersistenceStatus'); return $body; } diff --git a/src/Request/Request/AudioPlayer/AudioPlayerRequest.php b/src/Request/Request/AudioPlayer/AudioPlayerRequest.php index 5b3b1c8..203853d 100644 --- a/src/Request/Request/AudioPlayer/AudioPlayerRequest.php +++ b/src/Request/Request/AudioPlayer/AudioPlayerRequest.php @@ -2,6 +2,7 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\AudioPlayer; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; use MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest; /** @@ -38,6 +39,6 @@ protected function setRequestData(array $amazonRequest) $this->timestamp = (new \DateTime())->setTimestamp(intval($amazonRequest['timestamp'] / 1000)); } $this->locale = $amazonRequest['locale']; - $this->token = isset($amazonRequest['token']) ? $amazonRequest['token'] : null; + $this->token = PropertyHelper::checkNullValueString($amazonRequest, 'token'); } } diff --git a/src/Request/Request/AudioPlayer/PlaybackFinishedRequest.php b/src/Request/Request/AudioPlayer/PlaybackFinishedRequest.php index a1bcf22..e5f4924 100644 --- a/src/Request/Request/AudioPlayer/PlaybackFinishedRequest.php +++ b/src/Request/Request/AudioPlayer/PlaybackFinishedRequest.php @@ -2,6 +2,7 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\AudioPlayer; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; use MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest; /** @@ -24,7 +25,7 @@ public static function fromAmazonRequest(array $amazonRequest): AbstractRequest $request = new self(); $request->type = self::TYPE; - $request->offsetInMilliseconds = isset($amazonRequest['offsetInMilliseconds']) ? $amazonRequest['offsetInMilliseconds'] : null; + $request->offsetInMilliseconds = PropertyHelper::checkNullValueInt($amazonRequest, 'offsetInMilliseconds'); $request->setRequestData($amazonRequest); return $request; diff --git a/src/Request/Request/AudioPlayer/PlaybackNearlyFinishedRequest.php b/src/Request/Request/AudioPlayer/PlaybackNearlyFinishedRequest.php index d3f91bd..4c6116c 100644 --- a/src/Request/Request/AudioPlayer/PlaybackNearlyFinishedRequest.php +++ b/src/Request/Request/AudioPlayer/PlaybackNearlyFinishedRequest.php @@ -2,6 +2,7 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\AudioPlayer; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; use MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest; /** @@ -24,7 +25,7 @@ public static function fromAmazonRequest(array $amazonRequest): AbstractRequest $request = new self(); $request->type = self::TYPE; - $request->offsetInMilliseconds = isset($amazonRequest['offsetInMilliseconds']) ? $amazonRequest['offsetInMilliseconds'] : null; + $request->offsetInMilliseconds = PropertyHelper::checkNullValueInt($amazonRequest, 'offsetInMilliseconds'); $request->setRequestData($amazonRequest); return $request; diff --git a/src/Request/Request/AudioPlayer/PlaybackStartedRequest.php b/src/Request/Request/AudioPlayer/PlaybackStartedRequest.php index e33f08e..351d2b5 100644 --- a/src/Request/Request/AudioPlayer/PlaybackStartedRequest.php +++ b/src/Request/Request/AudioPlayer/PlaybackStartedRequest.php @@ -2,6 +2,7 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\AudioPlayer; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; use MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest; /** @@ -24,7 +25,7 @@ public static function fromAmazonRequest(array $amazonRequest): AbstractRequest $request = new self(); $request->type = self::TYPE; - $request->offsetInMilliseconds = isset($amazonRequest['offsetInMilliseconds']) ? $amazonRequest['offsetInMilliseconds'] : null; + $request->offsetInMilliseconds = PropertyHelper::checkNullValueInt($amazonRequest, 'offsetInMilliseconds'); $request->setRequestData($amazonRequest); return $request; diff --git a/src/Request/Request/AudioPlayer/PlaybackState.php b/src/Request/Request/AudioPlayer/PlaybackState.php index 4caaadf..8fa9340 100644 --- a/src/Request/Request/AudioPlayer/PlaybackState.php +++ b/src/Request/Request/AudioPlayer/PlaybackState.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\AudioPlayer; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -37,9 +39,9 @@ public static function fromAmazonRequest(array $amazonRequest): self { $playbackState = new self(); - $playbackState->token = isset($amazonRequest['token']) ? $amazonRequest['token'] : null; - $playbackState->offsetInMilliseconds = isset($amazonRequest['offsetInMilliseconds']) ? $amazonRequest['offsetInMilliseconds'] : null; - $playbackState->playerActivity = isset($amazonRequest['playerActivity']) ? $amazonRequest['playerActivity'] : null; + $playbackState->token = PropertyHelper::checkNullValueString($amazonRequest, 'token'); + $playbackState->offsetInMilliseconds = PropertyHelper::checkNullValueInt($amazonRequest, 'offsetInMilliseconds'); + $playbackState->playerActivity = PropertyHelper::checkNullValueString($amazonRequest, 'playerActivity'); return $playbackState; } diff --git a/src/Request/Request/AudioPlayer/PlaybackStoppedRequest.php b/src/Request/Request/AudioPlayer/PlaybackStoppedRequest.php index 0a81fcf..32a1169 100644 --- a/src/Request/Request/AudioPlayer/PlaybackStoppedRequest.php +++ b/src/Request/Request/AudioPlayer/PlaybackStoppedRequest.php @@ -2,6 +2,7 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\AudioPlayer; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; use MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest; /** @@ -24,7 +25,7 @@ public static function fromAmazonRequest(array $amazonRequest): AbstractRequest $request = new self(); $request->type = self::TYPE; - $request->offsetInMilliseconds = isset($amazonRequest['offsetInMilliseconds']) ? $amazonRequest['offsetInMilliseconds'] : null; + $request->offsetInMilliseconds = PropertyHelper::checkNullValueInt($amazonRequest, 'offsetInMilliseconds'); $request->setRequestData($amazonRequest); return $request; diff --git a/src/Request/Request/Standard/IntentRequest.php b/src/Request/Request/Standard/IntentRequest.php index 1b0ca5d..44a9029 100644 --- a/src/Request/Request/Standard/IntentRequest.php +++ b/src/Request/Request/Standard/IntentRequest.php @@ -2,6 +2,7 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\Standard; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; use MaxBeckers\AmazonAlexa\Intent\Intent; use MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest; @@ -34,7 +35,7 @@ public static function fromAmazonRequest(array $amazonRequest): AbstractRequest $request = new static(); $request->type = static::TYPE; - $request->dialogState = isset($amazonRequest['dialogState']) ? $amazonRequest['dialogState'] : null; + $request->dialogState = PropertyHelper::checkNullValueString($amazonRequest, 'dialogState'); $request->intent = Intent::fromAmazonRequest($amazonRequest['intent']); $request->setRequestData($amazonRequest); diff --git a/src/Request/Request/Standard/SessionEndedRequest.php b/src/Request/Request/Standard/SessionEndedRequest.php index a8cac2a..f0115c4 100644 --- a/src/Request/Request/Standard/SessionEndedRequest.php +++ b/src/Request/Request/Standard/SessionEndedRequest.php @@ -2,6 +2,7 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\Standard; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; use MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest; use MaxBeckers\AmazonAlexa\Request\Request\Error; @@ -30,7 +31,7 @@ public static function fromAmazonRequest(array $amazonRequest): AbstractRequest $request = new self(); $request->type = self::TYPE; - $request->reason = isset($amazonRequest['reason']) ? $amazonRequest['reason'] : null; + $request->reason = PropertyHelper::checkNullValueString($amazonRequest, 'reason'); $request->error = isset($amazonRequest['error']) ? Error::fromAmazonRequest($amazonRequest['error']) : null; $request->setRequestData($amazonRequest); diff --git a/src/Request/Request/System/Cause.php b/src/Request/Request/System/Cause.php index 5dfdd06..938ff25 100644 --- a/src/Request/Request/System/Cause.php +++ b/src/Request/Request/System/Cause.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\System; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -21,7 +23,7 @@ public static function fromAmazonRequest(array $amazonRequest): self { $cause = new self(); - $cause->requestId = isset($amazonRequest['requestId']) ? $amazonRequest['requestId'] : null; + $cause->requestId = PropertyHelper::checkNullValueString($amazonRequest, 'requestId'); return $cause; } diff --git a/src/Request/Request/System/ConnectionsResponseRequest.php b/src/Request/Request/System/ConnectionsResponseRequest.php index b0bec10..d392a6f 100644 --- a/src/Request/Request/System/ConnectionsResponseRequest.php +++ b/src/Request/Request/System/ConnectionsResponseRequest.php @@ -2,6 +2,7 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\System; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; use MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest; /** @@ -42,8 +43,8 @@ public static function fromAmazonRequest(array $amazonRequest): AbstractRequest $request = new self(); $request->type = self::TYPE; - $request->name = isset($amazonRequest['name']) ? $amazonRequest['name'] : null; - $request->token = isset($amazonRequest['token']) ? $amazonRequest['token'] : null; + $request->name = PropertyHelper::checkNullValueString($amazonRequest, 'name'); + $request->token = PropertyHelper::checkNullValueString($amazonRequest, 'token'); $request->status = isset($amazonRequest['status']) ? Status::fromAmazonRequest($amazonRequest['status']) : null; $request->payload = isset($amazonRequest['payload']) ? Payload::fromAmazonRequest($amazonRequest['payload']) : null; diff --git a/src/Request/Request/System/Payload.php b/src/Request/Request/System/Payload.php index b3bdf8f..8d12940 100644 --- a/src/Request/Request/System/Payload.php +++ b/src/Request/Request/System/Payload.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\System; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -36,9 +38,9 @@ public static function fromAmazonRequest(array $amazonRequest): self { $status = new self(); - $status->purchaseResult = isset($amazonRequest['purchaseResult']) ? $amazonRequest['purchaseResult'] : null; - $status->productId = isset($amazonRequest['productId']) ? $amazonRequest['productId'] : null; - $status->message = isset($amazonRequest['message']) ? $amazonRequest['message'] : null; + $status->purchaseResult = PropertyHelper::checkNullValueString($amazonRequest, 'purchaseResult'); + $status->productId = PropertyHelper::checkNullValueString($amazonRequest, 'productId'); + $status->message = PropertyHelper::checkNullValueString($amazonRequest, 'message'); return $status; } diff --git a/src/Request/Request/System/Status.php b/src/Request/Request/System/Status.php index ace774b..5984caf 100644 --- a/src/Request/Request/System/Status.php +++ b/src/Request/Request/System/Status.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request\Request\System; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -26,8 +28,8 @@ public static function fromAmazonRequest(array $amazonRequest): self { $status = new self(); - $status->code = isset($amazonRequest['code']) ? $amazonRequest['code'] : null; - $status->message = isset($amazonRequest['message']) ? $amazonRequest['message'] : null; + $status->code = PropertyHelper::checkNullValueString($amazonRequest, 'code'); + $status->message = PropertyHelper::checkNullValueString($amazonRequest, 'message'); return $status; } diff --git a/src/Request/Session.php b/src/Request/Session.php index fbf6acc..e9dd14e 100644 --- a/src/Request/Session.php +++ b/src/Request/Session.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -44,7 +46,7 @@ public static function fromAmazonRequest(array $amazonRequest): self $session = new self(); $session->new = isset($amazonRequest['new']) ? (bool) $amazonRequest['new'] : null; - $session->sessionId = isset($amazonRequest['sessionId']) ? $amazonRequest['sessionId'] : null; + $session->sessionId = PropertyHelper::checkNullValueString($amazonRequest, 'sessionId'); $session->application = isset($amazonRequest['application']) ? Application::fromAmazonRequest($amazonRequest['application']) : null; $session->attributes = isset($amazonRequest['attributes']) ? (array) $amazonRequest['attributes'] : []; $session->user = isset($amazonRequest['user']) ? User::fromAmazonRequest($amazonRequest['user']) : null; diff --git a/src/Request/System.php b/src/Request/System.php index 0e11fba..136c4b7 100644 --- a/src/Request/System.php +++ b/src/Request/System.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -44,8 +46,8 @@ public static function fromAmazonRequest(array $amazonRequest): self $system->application = isset($amazonRequest['application']) ? Application::fromAmazonRequest($amazonRequest['application']) : null; $system->user = isset($amazonRequest['user']) ? User::fromAmazonRequest($amazonRequest['user']) : null; $system->device = isset($amazonRequest['device']) ? Device::fromAmazonRequest($amazonRequest['device']) : null; - $system->apiAccessToken = isset($amazonRequest['apiAccessToken']) ? $amazonRequest['apiAccessToken'] : null; - $system->apiEndpoint = isset($amazonRequest['apiEndpoint']) ? $amazonRequest['apiEndpoint'] : null; + $system->apiAccessToken = PropertyHelper::checkNullValueString($amazonRequest, 'apiAccessToken'); + $system->apiEndpoint = PropertyHelper::checkNullValueString($amazonRequest, 'apiEndpoint'); return $system; } diff --git a/src/Request/User.php b/src/Request/User.php index 3001bab..4be5780 100644 --- a/src/Request/User.php +++ b/src/Request/User.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -31,9 +33,9 @@ public static function fromAmazonRequest(array $amazonRequest): self { $user = new self(); - $user->userId = isset($amazonRequest['userId']) ? $amazonRequest['userId'] : null; + $user->userId = PropertyHelper::checkNullValueString($amazonRequest, 'userId'); $user->permissions = isset($amazonRequest['permissions']) ? UserPermissions::fromAmazonRequest($amazonRequest['permissions']) : null; - $user->accessToken = isset($amazonRequest['accessToken']) ? $amazonRequest['accessToken'] : null; + $user->accessToken = PropertyHelper::checkNullValueString($amazonRequest, 'accessToken'); return $user; } diff --git a/src/Request/UserPermissions.php b/src/Request/UserPermissions.php index ad7e1f2..069f5ca 100644 --- a/src/Request/UserPermissions.php +++ b/src/Request/UserPermissions.php @@ -2,6 +2,8 @@ namespace MaxBeckers\AmazonAlexa\Request; +use MaxBeckers\AmazonAlexa\Helper\PropertyHelper; + /** * @author Maximilian Beckers */ @@ -21,7 +23,7 @@ public static function fromAmazonRequest(array $amazonRequest): self { $userPermissions = new self(); - $userPermissions->consentToken = isset($amazonRequest['consentToken']) ? $amazonRequest['consentToken'] : null; + $userPermissions->consentToken = PropertyHelper::checkNullValueString($amazonRequest, 'consentToken'); return $userPermissions; } diff --git a/src/Response/Card.php b/src/Response/Card.php index b4b1130..fd5440f 100644 --- a/src/Response/Card.php +++ b/src/Response/Card.php @@ -3,12 +3,15 @@ namespace MaxBeckers\AmazonAlexa\Response; use MaxBeckers\AmazonAlexa\Exception\InvalidCardPermissionsException; +use MaxBeckers\AmazonAlexa\Helper\SerializeValueMapper; /** * @author Maximilian Beckers */ class Card implements \JsonSerializable { + use SerializeValueMapper; + const TYPE_SIMPLE = 'Simple'; const TYPE_STANDARD = 'Standard'; const TYPE_LINK_ACCOUNT = 'LinkAccount'; @@ -130,21 +133,12 @@ public function jsonSerialize() { $data = new \ArrayObject(); - if (null !== $this->type) { - $data['type'] = $this->type; - } - if (null !== $this->title) { - $data['title'] = $this->title; - } - if (null !== $this->content) { - $data['content'] = $this->content; - } - if (null !== $this->text) { - $data['text'] = $this->text; - } - if (null !== $this->image) { - $data['image'] = $this->image; - } + $this->valueToArrayIfSet($data, 'type'); + $this->valueToArrayIfSet($data, 'title'); + $this->valueToArrayIfSet($data, 'content'); + $this->valueToArrayIfSet($data, 'text'); + $this->valueToArrayIfSet($data, 'image'); + if (!empty($this->permissions)) { $data['permissions'] = $this->permissions; } diff --git a/src/Response/Directives/AudioPlayer/Stream.php b/src/Response/Directives/AudioPlayer/Stream.php index 4b6d71e..9f4cb39 100644 --- a/src/Response/Directives/AudioPlayer/Stream.php +++ b/src/Response/Directives/AudioPlayer/Stream.php @@ -2,11 +2,15 @@ namespace MaxBeckers\AmazonAlexa\Response\Directives\AudioPlayer; +use MaxBeckers\AmazonAlexa\Helper\SerializeValueMapper; + /** * @author Maximilian Beckers */ class Stream implements \JsonSerializable { + use SerializeValueMapper; + /** * @var string */ @@ -52,17 +56,13 @@ public static function create(string $url, string $token, string $expectedPrevio */ public function jsonSerialize() { - $data = [ + $data = new \ArrayObject([ 'url' => $this->url, 'token' => $this->token, - ]; + ]); - if (null !== $this->expectedPreviousToken) { - $data['expectedPreviousToken'] = $this->expectedPreviousToken; - } - if (null !== $this->offsetInMilliseconds) { - $data['offsetInMilliseconds'] = $this->offsetInMilliseconds; - } + $this->valueToArrayIfSet($data, 'expectedPreviousToken'); + $this->valueToArrayIfSet($data, 'offsetInMilliseconds'); return $data; } diff --git a/src/Response/Directives/Display/ImageSource.php b/src/Response/Directives/Display/ImageSource.php index 07504b7..5cf3dc5 100644 --- a/src/Response/Directives/Display/ImageSource.php +++ b/src/Response/Directives/Display/ImageSource.php @@ -2,11 +2,15 @@ namespace MaxBeckers\AmazonAlexa\Response\Directives\Display; +use MaxBeckers\AmazonAlexa\Helper\SerializeValueMapper; + /** * @author Maximilian Beckers */ class ImageSource implements \JsonSerializable { + use SerializeValueMapper; + const SIZE_X_SMALL = 'X_SMALL'; const SIZE_SMALL = 'SMALL'; const SIZE_MEDIUM = 'MEDIUM'; @@ -60,18 +64,10 @@ public function jsonSerialize() { $data = new \ArrayObject(); - if (null !== $this->url) { - $data['url'] = $this->url; - } - if (null !== $this->size) { - $data['size'] = $this->size; - } - if (null !== $this->widthPixels) { - $data['widthPixels'] = $this->widthPixels; - } - if (null !== $this->heightPixels) { - $data['heightPixels'] = $this->heightPixels; - } + $this->valueToArrayIfSet($data, 'url'); + $this->valueToArrayIfSet($data, 'size'); + $this->valueToArrayIfSet($data, 'widthPixels'); + $this->valueToArrayIfSet($data, 'heightPixels'); return $data; } diff --git a/src/Response/Directives/Display/Template.php b/src/Response/Directives/Display/Template.php index 18a6b6e..67c4953 100644 --- a/src/Response/Directives/Display/Template.php +++ b/src/Response/Directives/Display/Template.php @@ -2,11 +2,15 @@ namespace MaxBeckers\AmazonAlexa\Response\Directives\Display; +use MaxBeckers\AmazonAlexa\Helper\SerializeValueMapper; + /** * @author Maximilian Beckers */ class Template implements \JsonSerializable { + use SerializeValueMapper; + const BACK_BUTTON_MODE_HIDDEN = 'HIDDEN'; const BACK_BUTTON_MODE_VISIBLE = 'VISIBLE'; @@ -93,27 +97,14 @@ public function jsonSerialize() { $data = new \ArrayObject(); - if (null !== $this->type) { - $data['type'] = $this->type; - } - if (null !== $this->token) { - $data['token'] = $this->token; - } - if (null !== $this->backButton) { - $data['backButton'] = $this->backButton; - } - if (null !== $this->backgroundImage) { - $data['backgroundImage'] = $this->backgroundImage; - } - if (null !== $this->title) { - $data['title'] = $this->title; - } - if (null !== $this->textContent) { - $data['textContent'] = $this->textContent; - } - if (null !== $this->image) { - $data['image'] = $this->image; - } + $this->valueToArrayIfSet($data, 'type'); + $this->valueToArrayIfSet($data, 'token'); + $this->valueToArrayIfSet($data, 'backButton'); + $this->valueToArrayIfSet($data, 'backgroundImage'); + $this->valueToArrayIfSet($data, 'title'); + $this->valueToArrayIfSet($data, 'textContent'); + $this->valueToArrayIfSet($data, 'image'); + if (!empty($this->listItems)) { $data['listItems'] = $this->listItems; } diff --git a/src/Response/Directives/Display/TextContent.php b/src/Response/Directives/Display/TextContent.php index d0d2049..24916c4 100644 --- a/src/Response/Directives/Display/TextContent.php +++ b/src/Response/Directives/Display/TextContent.php @@ -2,11 +2,15 @@ namespace MaxBeckers\AmazonAlexa\Response\Directives\Display; +use MaxBeckers\AmazonAlexa\Helper\SerializeValueMapper; + /** * @author Maximilian Beckers */ class TextContent implements \JsonSerializable { + use SerializeValueMapper; + /** * @var Text|null */ @@ -47,15 +51,9 @@ public function jsonSerialize() { $data = new \ArrayObject(); - if (null !== $this->primaryText) { - $data['primaryText'] = $this->primaryText; - } - if (null !== $this->secondaryText) { - $data['secondaryText'] = $this->secondaryText; - } - if (null !== $this->tertiaryText) { - $data['tertiaryText'] = $this->tertiaryText; - } + $this->valueToArrayIfSet($data, 'primaryText'); + $this->valueToArrayIfSet($data, 'secondaryText'); + $this->valueToArrayIfSet($data, 'tertiaryText'); return $data; } diff --git a/src/Response/ResponseBody.php b/src/Response/ResponseBody.php index 35018e1..0dcb99a 100644 --- a/src/Response/ResponseBody.php +++ b/src/Response/ResponseBody.php @@ -2,6 +2,7 @@ namespace MaxBeckers\AmazonAlexa\Response; +use MaxBeckers\AmazonAlexa\Helper\SerializeValueMapper; use MaxBeckers\AmazonAlexa\Response\Directives\Directive; /** @@ -9,6 +10,8 @@ */ class ResponseBody implements ResponseBodyInterface, \JsonSerializable { + use SerializeValueMapper; + /** * @var OutputSpeech|null */ @@ -51,18 +54,11 @@ public function jsonSerialize() { $data = new \ArrayObject(); - if (null !== $this->outputSpeech) { - $data['outputSpeech'] = $this->outputSpeech; - } - if (null !== $this->card) { - $data['card'] = $this->card; - } - if (null !== $this->reprompt) { - $data['reprompt'] = $this->reprompt; - } - if (null !== $this->shouldEndSession) { - $data['shouldEndSession'] = $this->shouldEndSession; - } + $this->valueToArrayIfSet($data, 'outputSpeech'); + $this->valueToArrayIfSet($data, 'card'); + $this->valueToArrayIfSet($data, 'reprompt'); + $this->valueToArrayIfSet($data, 'shouldEndSession'); + if (!empty($this->directives)) { $data['directives'] = $this->directives; } diff --git a/src/Validation/RequestValidator.php b/src/Validation/RequestValidator.php index 75af7ee..6be7112 100644 --- a/src/Validation/RequestValidator.php +++ b/src/Validation/RequestValidator.php @@ -193,17 +193,35 @@ private function parseCertData(string $certData): array */ private function validateCertContent(array $cert, string $localCertPath) { - // validate cert subject + $this->validateCertSubject($cert); + $this->validateCertValidTime($cert, $localCertPath); + } + + /** + * @param array $cert + * + * @throws RequestInvalidSignatureException + */ + private function validateCertSubject(array $cert) + { if (false === isset($cert['extensions']['subjectAltName']) || false === stristr($cert['extensions']['subjectAltName'], 'echo-api.amazon.com') ) { throw new RequestInvalidSignatureException('Cert subject error.'); } + } - // validate cert validTo time + /** + * @param array $cert + * @param string $localCertPath + * + * @throws OutdatedCertExceptionException + */ + private function validateCertValidTime(array $cert, string $localCertPath) + { if (false === isset($cert['validTo_time_t']) || time() > $cert['validTo_time_t'] || false === isset($cert['validFrom_time_t']) || time() < $cert['validFrom_time_t']) { if (file_exists($localCertPath)) { - @unlink($localCertPath); + /* @scrutinizer ignore-unhandled */ @unlink($localCertPath); } throw new OutdatedCertExceptionException('Cert is outdated.'); } diff --git a/test/Test/Helper/PropertyHelperTest.php b/test/Test/Helper/PropertyHelperTest.php new file mode 100644 index 0000000..2db9f05 --- /dev/null +++ b/test/Test/Helper/PropertyHelperTest.php @@ -0,0 +1,62 @@ + + */ +class PropertyHelperTest extends TestCase +{ + public function testCheckNullValueStringSuccess() + { + $key = 'test'; + $value = 'me'; + $data = [ + $key => $value, + ]; + + $this->assertEquals( + $value, + PropertyHelper::checkNullValueString($data, $key) + ); + } + + public function testCheckNullValueStringUnset() + { + $key = 'test'; + $value = 'me'; + $data = [ + $key => $value, + ]; + + $this->assertNull(PropertyHelper::checkNullValueString($data, 'unset')); + } + + public function testCheckNullValueIntSuccess() + { + $key = 'test'; + $value = 132; + $data = [ + $key => $value, + ]; + + $this->assertEquals( + $value, + PropertyHelper::checkNullValueInt($data, $key) + ); + } + + public function testCheckNullValueIntUnset() + { + $key = 'test'; + $value = 123; + $data = [ + $key => $value, + ]; + + $this->assertNull(PropertyHelper::checkNullValueInt($data, 'unset')); + } +} diff --git a/test/Test/Response/Directives/AudioTest.php b/test/Test/Response/Directives/AudioTest.php index bc9c7fb..fa2207f 100644 --- a/test/Test/Response/Directives/AudioTest.php +++ b/test/Test/Response/Directives/AudioTest.php @@ -24,12 +24,12 @@ public function testStream() $this->assertSame('testurl', $stream->url); $this->assertSame('token', $stream->token); - $json = [ + $json = new \ArrayObject([ 'url' => 'testurl', 'token' => 'token', - ]; + ]); - $this->assertSame($json, $stream->jsonSerialize()); + $this->assertEquals($json, $stream->jsonSerialize()); } public function testStreamAll() @@ -41,14 +41,14 @@ public function testStreamAll() $this->assertSame('prevToken', $stream->expectedPreviousToken); $this->assertSame(10, $stream->offsetInMilliseconds); - $json = [ + $json = new \ArrayObject([ 'url' => 'testurl', 'token' => 'token', 'expectedPreviousToken' => 'prevToken', 'offsetInMilliseconds' => 10, - ]; + ]); - $this->assertSame($json, $stream->jsonSerialize()); + $this->assertEquals($json, $stream->jsonSerialize()); } public function testAudioItem()