1<?php 2 3namespace ComboStrap; 4 5 6use ComboStrap\Web\Url; 7use ComboStrap\Web\UrlEndpoint; 8 9/** 10 * A request to the application 11 * It's now a wrapper around {@link \TestRequest} 12 */ 13class HttpRequest 14{ 15 16 const CANONICAL = "httpRequest"; 17 const POST = "post"; 18 const GET = "get"; 19 private bool $withTestRequest = true; 20 21 private Url $url; 22 private HttpResponse $response; 23 private string $method = self::GET; 24 private bool $asAdmin = false; 25 private array $postData = []; 26 27 28 public function __construct(Url $url) 29 { 30 $this->url = $url; 31 32 33 } 34 35 36 /** 37 * @param string $wikiId 38 * @return HttpResponse 39 * With the path uri: '/doku.php' 40 */ 41 public static function fetchXhtmlPageResponse(string $wikiId): HttpResponse 42 { 43 44 45 $url = FetcherPage::createPageFetcherFromId($wikiId) 46 ->getFetchUrl(); 47 48 49 return HttpRequest::createRequest($url) 50 ->withTestRequest() 51 ->fetch(); 52 53 } 54 55 56 private function withTestRequest(): HttpRequest 57 { 58 $this->withTestRequest = true; 59 return $this; 60 } 61 62 public static function createRequest(Url $url): HttpRequest 63 { 64 return new HttpRequest($url); 65 } 66 67 68 /** 69 * @param array $data - data post body as if it was from a form 70 * @return $this 71 */ 72 public function post(array $data = array()): HttpRequest 73 { 74 $this->method = self::POST; 75 $this->postData = $data; 76 return $this; 77 } 78 79 80 public function fetch(): HttpResponse 81 { 82 if (!$this->withTestRequest) { 83 84 throw new ExceptionRuntime("Real HTTP fetch not yet implemented, only test fetch"); 85 86 } 87 88 if (ExecutionContext::getActualOrCreateFromEnv()->response()->hasEnded()) { 89 /** 90 * As of today, the execution context is responsible to 91 * send back the response 92 * (There is no routing context, therefore for 93 * each http request, a new context needs to be created) 94 */ 95 throw new ExceptionRuntimeInternal("The execution context has ended, you should reopen another one"); 96 } 97 98 try { 99 $path = $this->url->getPath(); 100 if (!in_array($path, UrlEndpoint::DOKU_ENDPOINTS)) { 101 throw new ExceptionRuntime("The url path is not a doku endpoint path"); 102 } 103 } catch (ExceptionNotFound $e) { 104 throw new ExceptionRuntime("The path is mandatory"); 105 } 106 107 $testRequest = new \TestRequest(); 108 $testRequest->setServer('REQUEST_TIME', time()); 109 110 if ($this->asAdmin) { 111 Identity::becomeSuperUser($testRequest); 112 } 113 114 /** 115 * Deprecation are going into the HTML 116 * and break the parsing 117 */ 118 $level = error_reporting(E_ALL ^ (E_DEPRECATED)); 119 try { 120 switch ($this->method) { 121 case self::GET: 122 $query = $this->url->getQueryProperties(); 123 $response = $testRequest->get($query, $path); 124 break; 125 case self::POST: 126 $query = $this->url->getQueryProperties(); 127 foreach ($query as $queryKey => $queryValue) { 128 $testRequest->setGet($queryKey, $queryValue); 129 } 130 $response = $testRequest->post($this->postData, $path); 131 break; 132 default: 133 throw new ExceptionRuntime("The method ({$this->method}) is not implemented"); 134 } 135 } finally { 136 error_reporting($level); 137 } 138 139 140 return HttpResponse::createFromDokuWikiResponse($response); 141 } 142 143 public function asAdmin(): HttpRequest 144 { 145 $this->asAdmin = true; 146 return $this; 147 } 148 149 public function get(): HttpRequest 150 { 151 $this->method = self::GET; 152 return $this; 153 } 154 155 public function fetchAndExcuteBodyAsHtml(int $waitTimeInSecondToComplete = 0): HttpResponse 156 { 157 return $this->fetch()->executeBodyAsHtmlPage($waitTimeInSecondToComplete); 158 } 159 160 161} 162