/** * Make an AJAX request. * * @param array See $options http://docs.jquery.com/Ajax/jQuery.ajax#toptions * Additional options are: * 'document' - document for global events, @see pQuery::getDocumentID() * 'referer' - implemented * 'requested_with' - TODO; not implemented (X-Requested-With) * @return Zend_Http_Client * @link http://docs.jquery.com/Ajax/jQuery.ajax * * @TODO $options['cache'] * @TODO $options['processData'] * @TODO $options['xhr'] * @TODO $options['data'] as string * @TODO XHR interface */ public static function ajax($options = array(), $xhr = null) { $options = array_merge(self::$ajaxSettings, $options); $documentID = isset($options['document']) ? self::getDocumentID($options['document']) : null; if ($xhr) { // reuse existing XHR object, but clean it up $client = $xhr; // $client->setParameterPost(null); // $client->setParameterGet(null); $client->setAuth(false); $client->setHeaders("If-Modified-Since", null); $client->setHeaders("Referer", null); $client->resetParameters(); } else { // create new XHR object require_once 'Zend/Http/Client.php'; $client = new Zend_Http_Client(); $client->setCookieJar(); } if (isset($options['timeout'])) { $client->setConfig(array('timeout' => $options['timeout'])); } // 'maxredirects' => 0, foreach (self::$ajaxAllowedHosts as $k => $host) { if ($host == '.' && isset($_SERVER['HTTP_HOST'])) { self::$ajaxAllowedHosts[$k] = $_SERVER['HTTP_HOST']; } } $host = parse_url($options['url'], PHP_URL_HOST); if (!in_array($host, self::$ajaxAllowedHosts)) { throw new Exception("Request not permitted, host '{$host}' not present in " . "pQuery::\$ajaxAllowedHosts"); } // JSONP $jsre = "/=\\?(&|\$)/"; if (isset($options['dataType']) && $options['dataType'] == 'jsonp') { $jsonpCallbackParam = $options['jsonp'] ? $options['jsonp'] : 'callback'; if (strtolower($options['type']) == 'get') { if (!preg_match($jsre, $options['url'])) { $sep = strpos($options['url'], '?') ? '&' : '?'; $options['url'] .= "{$sep}{$jsonpCallbackParam}=?"; } } else { if ($options['data']) { $jsonp = false; foreach ($options['data'] as $n => $v) { if ($v == '?') { $jsonp = true; } } if (!$jsonp) { $options['data'][$jsonpCallbackParam] = '?'; } } } $options['dataType'] = 'json'; } if (isset($options['dataType']) && $options['dataType'] == 'json') { $jsonpCallback = 'json_' . md5(microtime()); $jsonpData = $jsonpUrl = false; if ($options['data']) { foreach ($options['data'] as $n => $v) { if ($v == '?') { $jsonpData = $n; } } } if (preg_match($jsre, $options['url'])) { $jsonpUrl = true; } if ($jsonpData !== false || $jsonpUrl) { // remember callback name for httpData() $options['_jsonp'] = $jsonpCallback; if ($jsonpData !== false) { $options['data'][$jsonpData] = $jsonpCallback; } if ($jsonpUrl) { $options['url'] = preg_replace($jsre, "={$jsonpCallback}\\1", $options['url']); } } } $client->setUri($options['url']); $client->setMethod(strtoupper($options['type'])); if (isset($options['referer']) && $options['referer']) { $client->setHeaders('Referer', $options['referer']); } $client->setHeaders(array('User-Agent' => 'Mozilla/5.0 (X11; U; Linux x86; en-US; rv:1.9.0.5) Gecko' . '/2008122010 Firefox/3.0.5', 'Accept-Charset' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'Accept-Language' => 'en-us,en;q=0.5')); if ($options['username']) { $client->setAuth($options['username'], $options['password']); } if (isset($options['ifModified']) && $options['ifModified']) { $client->setHeaders("If-Modified-Since", self::$lastModified ? self::$lastModified : "Thu, 01 Jan 1970 00:00:00 GMT"); } $client->setHeaders("Accept", isset($options['dataType']) && isset(self::$ajaxSettings['accepts'][$options['dataType']]) ? self::$ajaxSettings['accepts'][$options['dataType']] . ", */*" : self::$ajaxSettings['accepts']['_default']); // TODO $options['processData'] if ($options['data'] instanceof pQueryObject) { $serialized = $options['data']->serializeArray($options['data']); $options['data'] = array(); foreach ($serialized as $r) { $options['data'][$r['name']] = $r['value']; } } if (strtolower($options['type']) == 'get') { $client->setParameterGet($options['data']); } else { if (strtolower($options['type']) == 'post') { $client->setEncType($options['contentType']); $client->setParameterPost($options['data']); } } if (self::$active == 0 && $options['global']) { pQueryEvents::trigger($documentID, 'ajaxStart'); } self::$active++; // beforeSend callback if (isset($options['beforeSend']) && $options['beforeSend']) { pQuery::callbackRun($options['beforeSend'], array($client)); } // ajaxSend event if ($options['global']) { pQueryEvents::trigger($documentID, 'ajaxSend', array($client, $options)); } if (pQuery::$debug) { self::debug("{$options['type']}: {$options['url']}\n"); self::debug("Options: <pre>" . var_export($options, true) . "</pre>\n"); // if ($client->getCookieJar()) // self::debug("Cookies: <pre>".var_export($client->getCookieJar()->getMatchingCookies($options['url']), true)."</pre>\n"); } // request $response = $client->request(); if (pQuery::$debug) { self::debug('Status: ' . $response->getStatus() . ' / ' . $response->getMessage()); self::debug($client->getLastRequest()); self::debug($response->getHeaders()); } if ($response->isSuccessful()) { // XXX tempolary self::$lastModified = $response->getHeader('Last-Modified'); $data = self::httpData($response->getBody(), $options['dataType'], $options); if (isset($options['success']) && $options['success']) { pQuery::callbackRun($options['success'], array($data, $response->getStatus(), $options)); } if ($options['global']) { pQueryEvents::trigger($documentID, 'ajaxSuccess', array($client, $options)); } } else { if (isset($options['error']) && $options['error']) { pQuery::callbackRun($options['error'], array($client, $response->getStatus(), $response->getMessage())); } if ($options['global']) { pQueryEvents::trigger($documentID, 'ajaxError', array($client, $response->getMessage(), $options)); } } if (isset($options['complete']) && $options['complete']) { pQuery::callbackRun($options['complete'], array($client, $response->getStatus())); } if ($options['global']) { pQueryEvents::trigger($documentID, 'ajaxComplete', array($client, $options)); } if ($options['global'] && !--self::$active) { pQueryEvents::trigger($documentID, 'ajaxStop'); } return $client; // if (is_null($domId)) // $domId = self::$defaultDocumentID ? self::$defaultDocumentID : false; // return new pQueryAjaxResponse($response, $domId); }