Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • None
  • system
    • base
    • caching
    • console
    • db
      • ar
      • schema
    • validators
    • web
      • actions
      • auth
      • helpers
      • widgets
        • captcha
        • pagers
  • zii
    • widgets
      • grid

Classes

  • ActionCompleteTrigger
  • ActionOverdueTrigger
  • ActionUncompleteTrigger
  • BaseUserTrigger
  • BaseWorkflowStageTrigger
  • BaseWorkflowTrigger
  • BaseX2FlowEmail
  • BaseX2FlowWorkflowStageAction
  • CampaignEmailClickTrigger
  • CampaignEmailOpenTrigger
  • CampaignUnsubscribeTrigger
  • EmailOpenTrigger
  • InboundEmailTrigger
  • MacroTrigger
  • OutboundEmailTrigger
  • RecordCreateTrigger
  • RecordDeleteTrigger
  • RecordUpdateTrigger
  • RecordViewTrigger
  • UserLoginTrigger
  • UserLogoutTrigger
  • WorkflowCompleteStageTrigger
  • WorkflowCompleteTrigger
  • WorkflowRevertStageTrigger
  • WorkflowStartStageTrigger
  • WorkflowStartTrigger
  • X2FlowApiCall
  • X2FlowCreateAction
  • X2FlowCreateEvent
  • X2FlowCreateNotif
  • X2FlowEmail
  • X2FlowRecordComment
  • X2FlowRecordCreate
  • X2FlowRecordCreateAction
  • X2FlowRecordDelete
  • X2FlowRecordListAdd
  • X2FlowRecordListRemove
  • X2FlowRecordReassign
  • X2FlowRecordTag
  • X2FlowRecordUpdate
  • X2FlowSplitter
  • X2FlowSwitch
  • X2FlowWorkflowCompleteStage
  • X2FlowWorkflowRevertStage
  • X2FlowWorkflowStartStage
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /*****************************************************************************************
  3:  * X2Engine Open Source Edition is a customer relationship management program developed by
  4:  * X2Engine, Inc. Copyright (C) 2011-2016 X2Engine Inc.
  5:  * 
  6:  * This program is free software; you can redistribute it and/or modify it under
  7:  * the terms of the GNU Affero General Public License version 3 as published by the
  8:  * Free Software Foundation with the addition of the following permission added
  9:  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
 10:  * IN WHICH THE COPYRIGHT IS OWNED BY X2ENGINE, X2ENGINE DISCLAIMS THE WARRANTY
 11:  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 12:  * 
 13:  * This program is distributed in the hope that it will be useful, but WITHOUT
 14:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 15:  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
 16:  * details.
 17:  * 
 18:  * You should have received a copy of the GNU Affero General Public License along with
 19:  * this program; if not, see http://www.gnu.org/licenses or write to the Free
 20:  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 21:  * 02110-1301 USA.
 22:  * 
 23:  * You can contact X2Engine, Inc. P.O. Box 66752, Scotts Valley,
 24:  * California 95067, USA. or at email address contact@x2engine.com.
 25:  * 
 26:  * The interactive user interfaces in modified source and object code versions
 27:  * of this program must display Appropriate Legal Notices, as required under
 28:  * Section 5 of the GNU Affero General Public License version 3.
 29:  * 
 30:  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
 31:  * these Appropriate Legal Notices must retain the display of the "Powered by
 32:  * X2Engine" logo. If the display of the logo is not reasonably feasible for
 33:  * technical reasons, the Appropriate Legal Notices must display the words
 34:  * "Powered by X2Engine".
 35:  *****************************************************************************************/
 36: 
 37: /**
 38:  * X2FlowAction that calls a remote API
 39:  *
 40:  * @package application.components.x2flow.actions
 41:  */
 42: class X2FlowApiCall extends X2FlowAction {
 43: 
 44:     /**
 45:      * This will only ever by false during unit tests 
 46:      */
 47:     private static $_makeRequest;
 48: 
 49:     /**
 50:      * Allows request behavior of this class to be toggled during unit tests
 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:     //public $info = 'Call a remote API by requesting the specified URL. You can specify the request type and any variables to be passed with the request. To improve performance, the request will be put into a job queue unless you need it to execute immediately.';
 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:             // array('name'=>'immediate','label'=>'Call immediately?','type'=>'boolean','defaultVal'=>true),
109:             )));
110:     }
111: 
112:     /**
113:      * @param array $headerRows 
114:      * @return array
115:      */
116:     public function getHeaders ($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:      * @param array $headers 
128:      * @return string
129:      */
130:     public function formatHeaders ($headers) {
131:         $formattedHeaders = array ();
132:         foreach ($headers as $name => $value) {
133:             $formattedHeaders[] = $name.': '.$value;
134:         }
135:         return $formattedHeaders;
136:     }
137: 
138:     /**
139:      * Override parent method to add url validation. Present warning to user on flow save if
140:      * specified url points to same server as the one X2Engine is hosted on.
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:      * Try to prevent api requests to X2Engine's api. This is a looser check than
168:      * validateOptions (). ValidateOptions () is more likely to produce false positives which we 
169:      * wouldn't want to have effect flow execution.
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, // 5 second timeout
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:                     // make sure the URL is ready for GET params
214:                     $url .= strpos($url, '?') === false ? '?' : '&'; 
215:                     $url .= $data;
216:                 }else{
217:                     if ($this->parseOption ('jsonPayload', $params)) {
218:                         // nested JSON option
219:                         if (!isset ($headers['Content-Type']))
220:                             $headers['Content-Type'] = 'application/json'; 
221:                         $httpOptions['content'] = $data;
222:                     } else {
223:                         // set up default header for POST style data
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:                             // legacy flat JSON object support
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:                     // set up default header for POST style data
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: 
X2CRM Documentation API documentation generated by ApiGen 2.8.0