1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
36:
37: 38: 39: 40: 41:
42: class X2FlowApiCall extends X2FlowAction {
43:
44: 45: 46:
47: private static $_makeRequest;
48:
49: 50: 51:
52: public function getMakeRequest () {
53: if (!isset (self::$_makeRequest)) {
54: self::$_makeRequest = true;
55: }
56: return self::$_makeRequest;
57: }
58:
59: public $title = 'Remote API Call';
60:
61: public $info = 'Call a remote API by requesting the specified URL. You can specify the request type, HTTP headers, and any variables to be passed with the request.';
62:
63: public function paramRules(){
64: $httpVerbs = array(
65: 'GET' => Yii::t('studio', 'GET'),
66: 'POST' => Yii::t('studio', 'POST'),
67: 'PUT' => Yii::t('studio', 'PUT'),
68: 'DELETE' => Yii::t('studio', 'DELETE')
69: );
70:
71: return array_merge (parent::paramRules (), array (
72: 'title' => Yii::t('studio', $this->title),
73: 'info' => Yii::t('studio', $this->info),
74: 'modelClass' => 'API_params',
75: 'options' => array(
76: array(
77: 'name' => 'url', 'label' => Yii::t('studio', 'URL')
78: ),
79: array(
80: 'name' => 'method',
81: 'label' => Yii::t('studio', 'Method'),
82: 'type' => 'dropdown',
83: 'options' => $httpVerbs
84: ),
85: array(
86: 'name' => 'jsonPayload',
87: 'label' => Yii::t('studio', 'Use JSON payload?'),
88: 'type' => 'boolean',
89: 'defaulVal' => 0
90: ),
91: array(
92: 'name' => 'jsonBlob',
93: 'label' => Yii::t('studio', 'JSON'),
94: 'type' => 'text',
95: 'optional' => 1,
96: 'htmlOptions' => array (
97: 'style' => 'display: none;'
98: )
99: ),
100: array(
101: 'name' => 'attributes', 'optional' => 1
102: ),
103: array(
104: 'name' => 'headers',
105: 'type' => 'attributes',
106: 'optional' => 1
107: ),
108:
109: )));
110: }
111:
112: 113: 114: 115:
116: public function ($headerRows, $params) {
117: $headers = array();
118: foreach ($headerRows as $row) {
119: $name = X2Flow::parseValue ($row['name'], '', $params, false);
120: $value = X2Flow::parseValue ($row['value'], '', $params, false);
121: $headers[$name] = $value;
122: }
123: return $headers;
124: }
125:
126: 127: 128: 129:
130: public function ($headers) {
131: $formattedHeaders = array ();
132: foreach ($headers as $name => $value) {
133: $formattedHeaders[] = $name.': '.$value;
134: }
135: return $formattedHeaders;
136: }
137:
138: 139: 140: 141:
142: public function validateOptions(&$paramRules,$params=null,$staticValidation=false) {
143: list ($success, $message) = parent::validateOptions ($paramRules, $params, $staticValidation);
144: if (!$success) return array ($success, $message);
145: $url = $this->config['options']['url']['value'];
146:
147: $hostInfo = preg_replace ('/^https?:\/\//', '', Yii::app()->getAbsoluteBaseUrl ());
148: $url = preg_replace ('/^https?:\/\//', '', $url);
149: if ($staticValidation &&
150: gethostbyname ($url) === gethostbyname ($hostInfo)) {
151:
152: return array (
153: self::VALIDATION_WARNING,
154: Yii::t(
155: 'studio',
156: 'Warning: The url specified in your Remote API Call flow action points to the '.
157: 'same server that X2Engine is hosted on. This could mean that this flow makes '.
158: 'a request to X2Engine\'s API. Calling X2Engine\'s API from X2Flow is not '.
159: 'advised since it could potentially trigger this flow, resulting in an '.
160: 'infinite loop.'));
161: } else {
162: return array (true, $message);
163: }
164: }
165:
166: 167: 168: 169: 170:
171: private function validateUrl ($url) {
172: $absoluteBaseUrl = Yii::app()->getAbsoluteBaseUrl ();
173: $absoluteBaseUrl = preg_replace ('/^https?:\/\//', '', $absoluteBaseUrl);
174: $url = preg_replace ('/^https?:\/\//', '', $url);
175: if (preg_match ("/^".preg_quote ($absoluteBaseUrl, '/').".*\/api2?\/.*/", $url)) {
176: return false;
177: }
178: return true;
179: }
180:
181: public function execute(&$params){
182: $url = $this->parseOption('url', $params);
183: if(strpos($url,'http')===false){
184: $url = 'http://'.$url;
185: }
186: $method = $this->parseOption('method', $params);
187:
188: if($this->parseOption('immediate', $params) || true){
189: $headers = array ();
190: $httpOptions = array(
191: 'timeout' => 5,
192: 'method' => $method,
193: );
194: if (isset ($this->config['headerRows'])) {
195: $headers = $this->getHeaders ($this->config['headerRows'], $params);
196: }
197:
198: if ($method !== 'GET' && $this->parseOption ('jsonPayload', $params)) {
199: $data = $this->parseOption ('jsonBlob', $params);
200: } elseif(isset($this->config['attributes']) && !empty($this->config['attributes'])){
201: $data = array();
202: foreach($this->config['attributes'] as $param){
203: if(isset($param['name'],$param['value'])){
204: $data[$param['name']]=X2Flow::parseValue(
205: $param['value'],'',$params, false);
206: }
207: }
208: }
209:
210: if (isset ($data)) {
211: if($method === 'GET'){
212: $data = http_build_query($data);
213:
214: $url .= strpos($url, '?') === false ? '?' : '&';
215: $url .= $data;
216: }else{
217: if ($this->parseOption ('jsonPayload', $params)) {
218:
219: if (!isset ($headers['Content-Type']))
220: $headers['Content-Type'] = 'application/json';
221: $httpOptions['content'] = $data;
222: } else {
223:
224: if (!isset ($headers['Content-Type']))
225: $headers['Content-Type'] = 'application/x-www-form-urlencoded';
226:
227: if (preg_match ("/application\/json/", $headers['Content-Type'])) {
228:
229: $data = CJSON::encode ($data);
230: $httpOptions['content'] = $data;
231: } else {
232: $data = http_build_query($data);
233: $httpOptions['content'] = $data;
234: }
235: }
236:
237:
238: if (!isset ($headers['Content-Length']))
239: $headers['Content-Length'] = strlen($data);
240: }
241: }
242: if (count ($headers)) {
243: $formattedHeaders = $this->formatHeaders ($headers);
244: $httpOptions['header'] = implode("\r\n", $formattedHeaders);
245: }
246:
247: $context = stream_context_create(array('http' => $httpOptions));
248: if (!$this->validateUrl ($url)) {
249: if (YII_UNIT_TESTING) {
250: return array(
251: false,
252: array ('url' => $url)
253: );
254: } else {
255: return array(
256: false,
257: Yii::t('studio', 'Requests cannot be made to X2Engine\'s API from X2Flow.')
258: );
259: }
260: }
261: if (!$this->getMakeRequest ()) {
262: return array (true, array_merge (array ('url' => $url), $httpOptions));
263: } else {
264: $response = @file_get_contents($url, false, $context);
265: $params['returnValue'] = $response;
266: if ($response !== false) {
267: if (YII_UNIT_TESTING) {
268: return array(true, $response);
269: } else {
270: return array(true, Yii::t('studio', "Remote API call succeeded"));
271: }
272: }else{
273: if (YII_UNIT_TESTING) {
274: return array(false, print_r ($http_response_header, true));
275: } else {
276: return array(false, Yii::t('studio', "Remote API call failed!"));
277: }
278: }
279: }
280: }
281: }
282:
283: }
284: