{"action":"opened","issue":{"url":"https://api.github.com/repos/piwik/piwik/issues/8852","labels_url":"https://api.github.com/repos/piwik/piwik/issues/8852/labels{/name}","comments_url":"https://api.github.com/repos/piwik/piwik/issues/8852/comments","events_url":"https://api.github.com/repos/piwik/piwik/issues/8852/events","html_url":"https://github.com/piwik/piwik/issues/8852","id":108279746,"number":8852,"title":"New middleware feature: use API method parameter type hints to construct move parsing/validation outside of API methods","user":{"login":"diosmosis","id":125140,"avatar_url":"https://avatars.githubusercontent.com/u/125140?v=3","gravatar_id":"","url":"https://api.github.com/users/diosmosis","html_url":"https://github.com/diosmosis","followers_url":"https://api.github.com/users/diosmosis/followers","following_url":"https://api.github.com/users/diosmosis/following{/other_user}","gists_url":"https://api.github.com/users/diosmosis/gists{/gist_id}","starred_url":"https://api.github.com/users/diosmosis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diosmosis/subscriptions","organizations_url":"https://api.github.com/users/diosmosis/orgs","repos_url":"https://api.github.com/users/diosmosis/repos","events_url":"https://api.github.com/users/diosmosis/events{/privacy}","received_events_url":"https://api.github.com/users/diosmosis/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/piwik/piwik/labels/c:%20Platform","name":"c: Platform","color":"bfe5bf"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/piwik/piwik/milestones/75","html_url":"https://github.com/piwik/piwik/milestones/3.0.0","labels_url":"https://api.github.com/repos/piwik/piwik/milestones/75/labels","id":887285,"number":75,"title":"3.0.0","description":"","creator":{"login":"mattab","id":466765,"avatar_url":"https://avatars.githubusercontent.com/u/466765?v=3","gravatar_id":"","url":"https://api.github.com/users/mattab","html_url":"https://github.com/mattab","followers_url":"https://api.github.com/users/mattab/followers","following_url":"https://api.github.com/users/mattab/following{/other_user}","gists_url":"https://api.github.com/users/mattab/gists{/gist_id}","starred_url":"https://api.github.com/users/mattab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mattab/subscriptions","organizations_url":"https://api.github.com/users/mattab/orgs","repos_url":"https://api.github.com/users/mattab/repos","events_url":"https://api.github.com/users/mattab/events{/privacy}","received_events_url":"https://api.github.com/users/mattab/received_events","type":"User","site_admin":false},"open_issues":67,"closed_issues":1,"state":"open","created_at":"2014-12-02T02:19:24Z","updated_at":"2015-09-25T07:53:46Z","due_on":"2016-03-16T23:00:00Z","closed_at":null},"comments":0,"created_at":"2015-09-25T07:53:45Z","updated_at":"2015-09-25T07:53:45Z","closed_at":null,"body":"Currently API methods accept string values and are themselves responsible for parsing those values into a data structure and validating those values. Many API methods use common inputs though, for example, a list of site IDs or a list of dates. At the moment this results in code redundancy and often times code that isn't fully tested.\r\n\r\nWe can solve this for 3.0 by introducing a feature that is available in many MVC frameworks (including, eg Spring: http://stackoverflow.com/questions/16942193/spring-mvc-complex-object-as-get-requestparam). In `core/API/Proxy.php`, we can detect the type hints of API methods, construct those types w/ the query parameter values and pass them to the API methods, thus moving the responsibility of parsing & validating to Piwik's middleware.\r\n\r\nFor example, an API method that might've looked like this before:\r\n\r\n```\r\npublic function doSomething($sites, $dates)\r\n{\r\n    $sites = explode(',', $sites);\r\n    $sites = array_map('intval', $sites);\r\n    Piwik::checkUserHasAdminAccess($sites);\r\n\r\n    $dates = explode(',', $dates);\r\n    $dates = array_map('\\Piwik\\Date::factory', $dates);\r\n\r\n    // ...\r\n}\r\n```\r\n\r\nwould instead look like:\r\n\r\n```\r\npublic function doSomething(SitesList $sites, DatesList $dates)\r\n{\r\n    Piwik::checkUserHasAdminAccess($sites->getIdSites());\r\n\r\n    // ...\r\n}\r\n```\r\n\r\nShould increase code reuse, increase code testability, and well, gosh darnit, just look better.\r\n\r\nA related possibility, is allowing results to be complex types as well, but this isn't quite as important to Piwik since most of the time the result is a DataTable."}}