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

  • AccountsGridViewProfileWidget
  • ActionMenu
  • ActionsGridViewProfileWidget
  • ActionsQuickCreateRelationshipBehavior
  • ActiveDateRangeInput
  • ApplicationConfigBehavior
  • Attachments
  • ChatBox
  • CommonControllerBehavior
  • ContactMapInlineTags
  • ContactsGridViewProfileWidget
  • CronForm
  • CSaveRelationsBehavior
  • DateRangeInputsWidget
  • DocsGridViewProfileWidget
  • DocViewer
  • DocViewerProfileWidget
  • EButtonColumnWithClearFilters
  • EmailDeliveryBehavior
  • EmailProgressControl
  • EncryptedFieldsBehavior
  • EventsChartProfileWidget
  • FileUploader
  • FontPickerInput
  • Formatter
  • FormView
  • GridViewWidget
  • History
  • IframeWidget
  • ImportExportBehavior
  • InlineActionForm
  • InlineEmailAction
  • InlineEmailForm
  • InlineEmailModelBehavior
  • InlineQuotes
  • JSONEmbeddedModelFieldsBehavior
  • JSONFieldsDefaultValuesBehavior
  • LeadRoutingBehavior
  • LeftWidget
  • LoginThemeHelper
  • LoginThemeHelperBase
  • MarketingGridViewProfileWidget
  • MediaBox
  • MessageBox
  • MobileFormatter
  • MobileFormLayoutRenderer
  • MobileLayoutRenderer
  • MobileLoginThemeHelper
  • MobileViewLayoutRenderer
  • ModelFileUploader
  • NewWebLeadsGridViewProfileWidget
  • NormalizedJSONFieldsBehavior
  • NoteBox
  • OnlineUsers
  • OpportunitiesGridViewProfileWidget
  • Panel
  • ProfileDashboardManager
  • ProfileGridViewWidget
  • ProfileLayoutEditor
  • ProfilesGridViewProfileWidget
  • Publisher
  • PublisherActionTab
  • PublisherCalendarEventTab
  • PublisherCallTab
  • PublisherCommentTab
  • PublisherEventTab
  • PublisherSmallCalendarEventTab
  • PublisherTab
  • PublisherTimeTab
  • QuickContact
  • QuickCreateRelationshipBehavior
  • QuotesGridViewProfileWidget
  • RecordAliasesWidget
  • RecordViewLayoutManager
  • RecordViewWidgetManager
  • RememberPagination
  • Reminders
  • ResponseBehavior
  • ResponsiveHtml
  • SearchIndexBehavior
  • ServicesGridViewProfileWidget
  • SmallCalendar
  • SmartActiveDataProvider
  • SmartDataProviderBehavior
  • SmartSort
  • SocialForm
  • SortableWidgetManager
  • SortableWidgets
  • TagBehavior
  • TagCloud
  • TemplatesGridViewProfileWidget
  • TimeZone
  • TopContacts
  • TopSites
  • TransformedFieldStorageBehavior
  • TranslationLogger
  • TwitterFeed
  • TwoColumnSortableWidgetManager
  • UpdaterBehavior
  • UpdatesForm
  • UserIdentity
  • UsersChartProfileWidget
  • WorkflowBehavior
  • X2ActiveGridView
  • X2ActiveGridViewForSortableWidgets
  • X2AssetManager
  • X2AuthManager
  • X2ChangeLogBehavior
  • X2ClientScript
  • X2Color
  • X2DateUtil
  • X2FixtureManager
  • X2FlowFormatter
  • X2GridView
  • X2GridViewBase
  • X2GridViewForSortableWidgets
  • X2GridViewSortableWidgetsBehavior
  • X2LeadsGridViewProfileWidget
  • X2LinkableBehavior
  • X2ListView
  • X2PillBox
  • X2ProgressBar
  • X2SmartSearchModelBehavior
  • X2TimestampBehavior
  • X2TranslationBehavior
  • X2UrlRule
  • X2WebModule
  • X2Widget
  • X2WidgetList
  • 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: // Imports that are required by properties/methods of this behavior:
 38: Yii::import('application.models.Admin');
 39: Yii::import('application.models.Modules');
 40: Yii::import('application.components.util.FileUtil');
 41: Yii::import('application.modules.users.models.*');
 42: Yii::import('application.modules.media.models.Media');
 43: 
 44: 
 45: /**
 46:  * ApplicationConfigBehavior is a behavior for the application. It loads
 47:  * additional config paramenters that cannot be statically written in config/main
 48:  * and is also used for features in common with the console application.
 49:  *
 50:  * @property string $absoluteBaseUrl (read-only) the base URL of the web
 51:  *  application, independent of whether there is a web request.
 52:  * @property string $edition The "edition" of the software.
 53:  * @property array $editionHierarchy Information about software sets as defined
 54:  *  in the static configuration file protected/data/editionHierarchy.php
 55:  * @property array $editions (read-only) The editions that apply to the app.
 56:  * @property string $externalAbsoluteBaseUrl (read-only) the absolute base url
 57:  *  of the application to use when creating URLs to be viewed publicly
 58:  * @property string $externalWebRoot (read-only) The absolute base webroot URL
 59:  *  of the application to use when creating URLs to be viewed publicly, from
 60:  *  the internet (i.e. the web lead capture form, email tracking links, etc.)
 61:  * @property integer|bool $locked Integer (timestamp) if the application is
 62:  *  locked; false otherwise.
 63:  * @property string $lockFile Path to the lock file
 64:  * @property Admin $settings The admin model containing settings for the app.
 65:  * @property integer $suID (read-only) substitute user ID in the case that no
 66:  *  user session is available.
 67:  * @property User $suModel Substitute web user model in the case that no user
 68:  *  session is available.
 69:  * @package application.components
 70:  */
 71: class ApplicationConfigBehavior extends CBehavior {
 72: 
 73:     /**
 74:      * Stores information about software edition sets (for manually setting
 75:      * edition, when testing software subsets)
 76:      * @var type
 77:      */
 78:     private static $_editions;
 79: 
 80:     /**
 81:      * Software edition detection based on logo presence.
 82:      * @var type 
 83:      */
 84:     private static $_logoHashes = array(
 85:         'pro'=> '0e666bd65d6204fa76ea1aec2a0f3217',
 86:         'pla'=> '1d4ffaf4d1f7af03f294217214a63fd2'
 87:     );
 88: 
 89:     private $_absoluteBaseUrl;
 90:     private $_edition;
 91:     private $_externalAbsoluteBaseUrl;
 92:     private $_externalWebRoot;
 93:     private $_externalWebDomain;
 94: 
 95:     /**
 96:      * Signifies whether the CryptUtil method has been initialized already
 97:      * @var bool
 98:      */
 99:     private $_cryptInit = false;
100:     private $_settings;
101:     
102:     /**
103:      * If the application is locked, this will be an integer corresponding to
104:      * the date that the application was locked. Otherwise, it will be false.
105:      * @var mixed
106:      */
107:     private $_locked;
108: 
109: 
110:     /**
111:      * Substitute user ID. Used in the case of API calls and console commands
112:      * when the web user component is not available (because there is no user
113:      * session in such cases).
114:      *
115:      * @var integer
116:      */
117:     private $_suID;
118: 
119:     /**
120:      * Substitute user model (used in api and console scenarios)
121:      * @var User
122:      */
123:     private $_suModel;
124: 
125:     /**
126:      * Distinguishes whether the model is being used inside an actual user session.
127:      * @var bool
128:      */
129:     private $_isInSession;
130: 
131:     /**
132:      * Declares events and the event handler methods.
133:      *
134:      * See yii documentation on behavior; this is an override of
135:      * {@link CBehavior::events()}
136:      */
137:     public function events(){
138:         return array_merge(parent::events(), array(
139:             'onBeginRequest' => 'beginRequest',
140:         ));
141:     }
142: 
143:     public function getUpdateServer() {
144:         return X2_UPDATE_BETA ? 'http://beta.x2planet.com' : 'https://x2planet.com';
145:     }
146: 
147:     /**
148:      * Returns a JS string which declares two global JS dictionaries if they haven't already been 
149:      * declared. Additional properties of the yii global are declared if the user has a profile.
150:      * The globals would already have been decalared in the case that this is an AJAX request in 
151:      * which registered scripts are being sent back in response to the client.
152:      *
153:      * @param object if set, additional profile specific properties are declared
154:      * @returns string A JS string
155:      */
156:     public function getJSGlobalsSetupScript ($profile=null) {
157:         if ($profile) {
158:             $notificationSound = '';
159:             if(!empty($profile->notificationSound) && is_numeric ($profile->notificationSound)) {
160:                 $notificationSound = Yii::app()->createExternalUrl('/media/media/getFile', array(
161:                     'id' => $profile->notificationSound,
162:                 ));
163:             }
164:         }
165:         $yii = array (
166:             'baseUrl' => $this->owner->baseUrl,
167:             'absoluteBaseUrl' => $this->owner->absoluteBaseUrl,
168:             'scriptUrl' => $this->owner->request->scriptUrl,
169:             'themeBaseUrl' => $this->owner->theme->baseUrl,
170:             'language' =>
171:                 ($this->owner->language == 'en' ? '' : $this->owner->getLanguage()),
172:             'datePickerFormat' => Formatter::formatDatePicker('medium'),
173:             'timePickerFormat' => Formatter::formatTimePicker(),
174:         );
175:         if ($profile) {
176:             $yii['profile'] = $profile->getAttributes ();
177:             $yii['notificationSoundPath'] = $notificationSound;
178:         }
179:         $x2 = array (
180:             'DEBUG' => YII_DEBUG,
181:             'DEV_MODE' => X2_DEV_MODE,
182:             'UNIT_TESTING' => YII_UNIT_TESTING,
183:             'isGuest' => !$this->owner->params->noSession && $this->owner->user->getIsGuest(),
184:             'notifUpdateInterval' => $this->settings->chatPollTime,
185:             'isAndroid' => AuxLib::isAndroid (),
186:             'isIPad' => AuxLib::isIPad (),
187:             'isMobileApp' => $this->isMobileApp (),
188:             'isPhoneGap' => $this->isPhoneGap (),
189:         );
190:         $setX2 = '';
191:         foreach ($x2 as $key => $val) {
192:             $setX2 .= "x2.$key = ".CJSON::encode ($val).";\n";
193:         }
194:         return '
195:             ;(function () {
196:                 if (typeof yii === "undefined") {
197:                     yii = '.CJSON::encode (
198:                         $yii
199:                     ).';
200:                 }
201:                 if (typeof x2 === "undefined") {
202:                     x2 = {};
203:                 }
204:                 '.$setX2.'
205:             }) ();
206:         ';
207:     }
208: 
209:     /**
210:      * Load dynamic app configuration.
211:      *
212:      * Per the onBeginRequest key in the array returned by {@link events()},
213:      * this method will be called when the request has begun. It allows for
214:      * many extra configuration tasks to be run on a per-request basis
215:      * without having to extend {@link Yii} and override its methods.
216:      */
217:     public function beginRequest(){
218:         // About the "noSession" property/variable:
219:         //
220:         // This variable, if true, indicates that the application is running in
221:         // the context of either an API call or a console command, in which case
222:         // there would not be the typical authenticated user and session
223:         // variables one would need in a web request
224:         //
225:         // It's necessary because originally this method was written with
226:         // absolutely no regard for compatibility with the API or Yii console,
227:         // and thus certain lines of code that make references to the usual web
228:         // environment with cookie-based authentication (which would fail in
229:         // those cases) needed to be kept inside of conditional statements that
230:         // are skipped over if in the console/API.
231:         $this->owner->params->noSession =
232:                 $this->owner->params->noSession
233:                 || strpos($this->owner->request->getPathInfo(),'api/')===0
234:                 || strpos($this->owner->request->getPathInfo(),'api2/')===0;
235:         $noSession = $this->owner->params->noSession;
236: 
237:         if(!$noSession){
238:             if($this->owner->request->getPathInfo() == 'notifications/get'){ // skip all the loading if this is a chat/notification update
239:                 Yii::import('application.models.Events');
240:                 Yii::import('application.components.X2ActiveRecordBehavior');
241:                 Yii::import('application.components.X2UrlManager');
242:                 Yii::import('application.components.Formatter');
243:                 Yii::import('application.components.FieldFormatter');
244:                 Yii::import('application.controllers.x2base');
245:                 Yii::import('application.controllers.X2Controller');
246:                 Yii::import('application.components.util.AuxLib');
247:                 Yii::import('application.models.Roles');
248:                 Yii::import('application.components.X2AuthManager');
249:                 Yii::import('application.components.X2Html');
250:                 Yii::import('application.components.X2WebUser');
251:                 Yii::import('application.components.sortableWidget.*');
252:                 Yii::import('application.components.sortableWidget.profileWidgets.*');
253:                 Yii::import('application.components.sortableWidget.recordViewWidgets.*');
254:                  
255:                 Yii::import('application.components.X2Settings.*');
256:                 Yii::import('application.components.X2MessageSource');
257:                 Yii::import('application.components.X2Html');
258:                 Yii::import('application.components.JSONEmbeddedModelFieldsBehavior');
259:                 Yii::import('application.components.X2MergeableBehavior');
260:                 Yii::import('application.components.TransformedFieldStorageBehavior');
261:                 Yii::import('application.components.EncryptedFieldsBehavior');
262:                 Yii::import('application.components.permissions.*');
263:                 Yii::import('application.models.Modules');
264:                 // import all the models
265:                 Yii::import('application.models.Social');
266:                 Yii::import('application.models.Profile');
267:                 Yii::import('application.models.Notification');
268:                 Yii::import('application.models.Fields');
269:                 foreach(scandir('protected/modules') as $module){
270:                     if(file_exists('protected/modules/'.$module.'/register.php'))
271:                         Yii::import('application.modules.'.$module.'.models.*');
272:                 }
273:                 if(!$this->owner->user->getIsGuest())
274:                     $profData = $this->owner->db->createCommand()
275:                         ->select('timeZone, language')
276:                         ->from('x2_profile')
277:                         ->where('id='.$this->owner->user->getId())->queryRow(); // set the timezone to the admin's
278:                 if(isset($profData)){
279:                     if(isset($profData['timeZone'])){
280:                         $timezone = $profData['timeZone'];
281:                     }
282:                     if(isset($profData['language'])){
283:                         $language = $profData['language'];
284:                     }else{
285: 
286:                     }
287:                 }
288:                 if(!isset($timezone))
289:                     $timezone = 'UTC';
290:                 if(!isset($language))
291:                     $language = 'en';
292:                 date_default_timezone_set($timezone);
293:                 $this->owner->language = $language;
294:                 Yii::import('application.models.X2ActiveRecord');
295:                 Yii::import('application.models.X2Model');
296:                 Yii::import('application.models.Dropdowns');
297:                 Yii::import('application.models.Admin');
298:                 $this->cryptInit();
299:                 
300:                 // Yii::import('application.models.*');
301:                 // foreach(scandir('protected/modules') as $module){
302:                 // if(file_exists('protected/modules/'.$module.'/register.php'))
303:                 // Yii::import('application.modules.'.$module.'.models.*');
304:                 // }
305:                 return;
306:             }
307:         }else{
308:             Yii::import('application.models.X2ActiveRecord');
309:             Yii::import('application.models.Profile');
310:             Yii::import('application.components.sortableWidget.*');
311:             Yii::import('application.components.X2Settings.*');
312:             Yii::import('application.components.TransformedFieldStorageBehavior');
313:             // Set time zone based on the default value
314:             date_default_timezone_set(Profile::model()->tableSchema->getColumn('timeZone')->defaultValue);
315:         }
316: 
317:         $this->importDirectories();
318:         
319:         $this->cryptInit();
320: 
321:         if (YII_DEBUG) $this->owner->params->timer = new TimerUtil;
322:         
323:         $this->owner->messages->onMissingTranslation = array(new TranslationLogger, 'log');
324: 
325:         // Set profile
326:         //
327:         // Get the Administrator's and the current user's profile.
328:         $adminProf = Profile::model()->findByPk(1);
329:         $this->owner->params->adminProfile = $adminProf;
330: 
331:         // Use a separate domain for static assets if requested
332:         if ($this->owner->settings->enableAssetDomains)
333:             Yii::app()->assetManager->enableAssetDomains();
334: 
335:         if(!$noSession){ // Typical web session:
336:             $notGuest = !$this->owner->user->getIsGuest();
337: 
338:             if($notGuest) {
339:                 $this->owner->params->profile = X2Model::model('Profile')->findByAttributes(array(
340:                     'username' => $this->owner->user->getName()
341:                         ));
342:                 $this->setSuModel($this->owner->params->profile->user);
343:             } else {
344:                 $this->owner->params->profile = Profile::model ()->getGuestProfile ();
345:             }
346:         } else {
347:             // Use the admin profile as the user profile.
348:             //
349:             // If a different profile is desired in an API call or console
350:             // command, a different profile should be loaded.
351:             //
352:             // Using "admin" as the default profile should not affect
353:             // permissions (that's what the "suModel" property is for). It is
354:             // merely to account for cases where there is a reference to the
355:             // "profile" property of some model or component class that would
356:             // break the application outside the scope of a web request with a
357:             // session and cookie-based authentication.
358:             $notGuest = false;
359:             $this->owner->params->profile = $adminProf;
360:             $userModel = $this->owner->params->profile->user;
361:             $this->setSuModel($userModel instanceof User
362:                     ? $userModel
363:                     : User::model()->findByPk(1));
364:         }
365:         
366:         
367:         // Set session variables
368:         if(!$noSession){
369:             $sessionId = isset($_SESSION['sessionId']) ? $_SESSION['sessionId'] : session_id();
370:             $session = X2Model::model('Session')->findByPk($sessionId);
371:             if(!empty($this->owner->params->profile)){
372:                 $_SESSION['fullscreen'] = $this->owner->params->profile->fullscreen;
373:             }
374:             if(!($this->owner->request->getPathInfo() == 'site/getEvents')){
375:                 if($notGuest){
376:                     $this->owner->user->setReturnUrl($this->owner->request->requestUri);
377:                     if($session != null){
378:                         $timeout = Roles::getUserTimeout($this->owner->user->getId());
379:                         if($session->lastUpdated + $timeout < time()){
380:                             SessionLog::logSession($this->owner->user->getName(), $sessionId, 'activeTimeout');
381:                             $session->delete();
382:                             $this->owner->user->logout(false);
383:                             $this->_suModel = null;
384:                             $this->_suID = null;
385:                             $this->setUserAccessParameters(null);
386:                         }else{
387:                             // Print a warning message
388:                             if($this->owner->session['debugEmailWarning']){
389:                                 $this->owner->session['debugEmailWarning'] = 0;
390:                                 $this->owner->user->setFlash('admin.debugEmailMode',
391:                                         Yii::t('app', 'Note, email debugging mode '
392:                                                 . 'is enabled. Emails will not '
393:                                                 . 'actually be delivered.'));
394:                             }
395: 
396:                             $session->lastUpdated = time();
397:                             $session->update(array('lastUpdated'));
398: 
399:                             $this->owner->params->sessionStatus = $session->status;
400:                         }
401:                     }else{
402:                         $this->owner->user->logout(false);
403:                         if ($this->isMobileApp () || $this->isPhoneGap ()) {
404:                             $this->owner->getRequest ()->redirect (
405:                                 $this->owner->createUrl('mobile/login'));
406:                         } else {
407:                             $this->owner->getRequest ()->redirect (
408:                                 $this->owner->createUrl('site/login'));
409:                         }
410:                     }
411:                 }else{
412:                     // Guest
413:                     $this->setUserAccessParameters(null);
414:                 }
415:             }
416:         }
417: 
418:         // Configure logos
419:         if(!($logo = $this->owner->cache['x2Power'])){
420:             $logo = 'data:image/png;base64,'.base64_encode(
421:                 file_get_contents(implode(DIRECTORY_SEPARATOR, array(
422:                     Yii::app()->basePath,
423:                     '..',
424:                     'images',
425:                     'powered_by_x2engine.png'
426:             ))));
427:             $this->owner->cache['x2Power'] = $logo;
428:         }
429:         $this->owner->params->x2Power = $logo;
430: 
431:         // Set currency and load currency symbols
432:         $this->owner->params->currency = $this->settings->currency;
433:         $locale = $this->owner->locale;
434:         $curSyms = array();
435:         foreach($this->owner->params->supportedCurrencies as $curCode){
436:             $curSyms[$curCode] = $locale->getCurrencySymbol($curCode);
437:         }
438:         $this->owner->params->supportedCurrencySymbols = $curSyms; // Code to symbol
439: 
440:         // Set language
441:         if(!empty($this->owner->params->profile->language) && $notGuest)
442:             $this->owner->language = $this->owner->params->profile->language;
443:         else if(isset($adminProf))
444:             $this->owner->language = $adminProf->language;
445: 
446:         // Set timezone
447:         if(!empty($this->owner->params->profile->timeZone) && $notGuest)
448:             date_default_timezone_set($this->owner->params->profile->timeZone);
449:         elseif(!empty($adminProf->timeZone))
450:             date_default_timezone_set($adminProf->timeZone);
451:         else
452:             date_default_timezone_set('UTC');
453:         setlocale(LC_ALL, 'en_US.UTF-8');
454: 
455:         // Set base path and theme path globals for JS (web UI only)
456:         if(!$noSession){
457:             if($notGuest){
458:                 $profile = $this->owner->params->profile;
459:                 if(isset($profile)){
460:                     $yiiString = $this->getJSGlobalsSetupScript ($profile);
461:                 }else{
462:                     $yiiString = $this->getJSGlobalsSetupScript ();
463:                 }
464:                 if(!$this->owner->request->isAjaxRequest) {
465:                     
466: Yii::app()->clientScript->registerScript(sprintf('%x', crc32(Yii::app()->name)), base64_decode(
467:     'dmFyIF8weDZjNzM9WyJceDc1XHg2RVx4NjRceDY1XHg2Nlx4NjlceDZFXHg2NVx4NjQiLCJceDZDXHg2R'
468:     .'lx4NjFceDY0IiwiXHgyM1x4NzBceDZGXHg3N1x4NjVceDcyXHg2NVx4NjRceDJEXHg2Mlx4NzlceDJEX'
469:     .'Hg3OFx4MzJceDY1XHg2RVx4NjdceDY5XHg2RVx4NjUiLCJceDZEXHg2Rlx4NjJceDY5XHg2Q1x4NjUiL'
470:     .'CJceDZDXHg2NVx4NkVceDY3XHg3NFx4NjgiLCJceDMyXHgzNVx4MzNceDY0XHg2NVx4NjRceDY1XHgzM'
471:     .'Vx4NjRceDMxXHg2Mlx4NjRceDYzXHgzMFx4NjJceDY1XHgzM1x4NjZceDMwXHgzM1x4NjNceDMzXHgzO'
472:     .'Fx4NjNceDY1XHgzN1x4MzRceDMzXHg2Nlx4MzZceDM5XHg2M1x4MzNceDMzXHgzN1x4MzRceDY0XHgzM'
473:     .'Vx4NjVceDYxXHg2Nlx4MzBceDM5XHg2M1x4NjVceDMyXHgzM1x4MzVceDMxXHg2Nlx4MzBceDM2XHgzM'
474:     .'lx4NjNceDM3XHg2M1x4MzBceDY1XHgzMlx4NjRceDY1XHgzMlx4MzZceDM0IiwiXHg3M1x4NzJceDYzI'
475:     .'iwiXHg2MVx4NzRceDc0XHg3MiIsIlx4M0FceDc2XHg2OVx4NzNceDY5XHg2Mlx4NkNceDY1IiwiXHg2O'
476:     .'Vx4NzMiLCJceDY4XHg2OVx4NjRceDY0XHg2NVx4NkUiLCJceDc2XHg2OVx4NzNceDY5XHg2Mlx4Njlce'
477:     .'DZDXHg2OVx4NzRceDc5IiwiXHg2M1x4NzNceDczIiwiXHg2OFx4NjVceDY5XHg2N1x4NjhceDc0IiwiX'
478:     .'Hg3N1x4NjlceDY0XHg3NFx4NjgiLCJceDZGXHg3MFx4NjFceDYzXHg2OVx4NzRceDc5IiwiXHg3M1x4N'
479:     .'zRceDYxXHg3NFx4NjlceDYzIiwiXHg3MFx4NkZceDczXHg2OVx4NzRceDY5XHg2Rlx4NkUiLCJceDY4X'
480:     .'Hg3Mlx4NjVceDY2IiwiXHg3Mlx4NjVceDZEXHg2Rlx4NzZceDY1XHg0MVx4NzRceDc0XHg3MiIsIlx4N'
481:     .'jEiLCJceDUwXHg2Q1x4NjVceDYxXHg3M1x4NjVceDIwXHg3MFx4NzVceDc0XHgyMFx4NzRceDY4XHg2N'
482:     .'Vx4MjBceDZDXHg2Rlx4NjdceDZGXHgyMFx4NjJceDYxXHg2M1x4NkJceDJFIiwiXHg2Rlx4NkUiXTtpZ'
483:     .'ihfMHg2YzczWzBdIT09IHR5cGVvZiBqUXVlcnkmJl8weDZjNzNbMF0hPT0gdHlwZW9mIFNIQTI1Nil7J'
484:     .'Ch3aW5kb3cpW18weDZjNzNbMjJdXShfMHg2YzczWzFdLGZ1bmN0aW9uKCl7dmFyIF8weDZlYjh4MT0kK'
485:     .'F8weDZjNzNbMl0pOyRbXzB4NmM3M1szXV18fF8weDZlYjh4MVtfMHg2YzczWzRdXSYmXzB4NmM3M1s1X'
486:     .'T09U0hBMjU2KF8weDZlYjh4MVtfMHg2YzczWzddXShfMHg2YzczWzZdKSkmJl8weDZlYjh4MVtfMHg2Y'
487:     .'zczWzldXShfMHg2YzczWzhdKSYmXzB4NmM3M1sxMF0hPV8weDZlYjh4MVtfMHg2YzczWzEyXV0oXzB4N'
488:     .'mM3M1sxMV0pJiYwIT1fMHg2ZWI4eDFbXzB4NmM3M1sxM11dKCkmJjAhPV8weDZlYjh4MVtfMHg2YzczW'
489:     .'zE0XV0oKSYmMT09XzB4NmViOHgxW18weDZjNzNbMTJdXShfMHg2YzczWzE1XSkmJl8weDZjNzNbMTZdP'
490:     .'T1fMHg2ZWI4eDFbXzB4NmM3M1sxMl1dKF8weDZjNzNbMTddKXx8KCQoXzB4NmM3M1syMF0pW18weDZjN'
491:     .'zNbMTldXShfMHg2YzczWzE4XSksYWxlcnQoXzB4NmM3M1syMV0pKTt9KX07Cg=='));
492: 
493:                 }
494:             }else{
495:                 $yiiString = $this->getJSGlobalsSetupScript ();
496:             }
497: 
498:             $this->owner->clientScript->registerScript(
499:                 'setParams', $yiiString, CClientScript::POS_HEAD);
500:             $cs = $this->owner->clientScript;
501:             $baseUrl = $this->owner->request->baseUrl;
502:             $jsVersion = '?'.$this->owner->params->buildDate;
503:             /**
504:              * To be restored when JavaScript minification is added to the build process:
505:              * $cs->scriptMap=array(
506:              * 'backgroundImage.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
507:              * 'json2.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
508:              * 'layout.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
509:              * 'media.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
510:              * 'modernizr.custom.66175.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
511:              * 'publisher.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
512:              * //'relationships.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
513:              * 'tags.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
514:              * 'translator.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
515:              * 'widgets.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
516:              * 'x2forms.js'=>$baseUrl.'/js/all.min.js'.$jsVersion,
517:              * ); */
518:         }
519:     }
520: 
521:     /**
522:      * Returns true or false for whether or not the application's current edition
523:      * contains a given edition.
524:      * 
525:      * @param string $edition The edition. With "opensource", this function will
526:      *  always evaluate to true.
527:      * @return boolean
528:      */
529:     public function contEd($edition) {
530:         return (bool) $this->editionHierarchy[$this->getEdition()][$edition];
531:     }
532: 
533:     /**
534:      * Instantiates the encryption utility object so that components depending
535:      * on {@link EncryptedFieldsBehavior} can also be instantiated.
536:      */
537:     public function cryptInit(){
538:         if(!$this->_cryptInit){
539:             $key = $this->owner->basePath.'/config/encryption.key';
540:             $iv = $this->owner->basePath.'/config/encryption.iv';
541:             if(extension_loaded('openssl') && extension_loaded('mcrypt') && file_exists($key) && file_exists($iv)){
542:                 EncryptedFieldsBehavior::setup($key, $iv);
543:             }else{
544:                 // Use unsafe method with encryption
545:                 EncryptedFieldsBehavior::setupUnsafe();
546:             }
547:         }
548:     }
549: 
550:     /**
551:      * Creates an URL that is safe to use for public-facing assets.
552:      *
553:      * In the case that there is no web request, but the "external" web root is
554:      * defined, the $_SERVER superglobal doesn't have necessary indexes like
555:      * "SERVER_PROTOCOL" to construct valid URLs. However, using the user-defined
556:      * external web root, it will explicitly use the route to generate the URL
557:      * (and assume the "path" format is always used for URLs).
558:      *
559:      * The solution ("Offline URL generation" should really be replaced with
560:      * something more elegant in the future. It is a crude attempt to replicate
561:      * URL creation for offline-generated URLs, i.e. for a console command that
562:      * sends emails. It was deemed, at the time of this special case's writing,
563:      * impractical to override CUrlManager.createUrl due to the complexity and
564:      * number of places where the $_SERVER superglobal (which any solution would
565:      * need to eliminate dependency thereupon) is referenced / depended upon.
566:      *
567:      * Provided the convention of always using absolute (and never relative)
568:      * routes is always adhered to, and the URL style remains "path", this
569:      * kludge should always work.
570:      *
571:      * @param string $route The module/controller/action route
572:      * @param array $params Query parameters
573:      */
574:     public function createExternalUrl($route, $params = array()){
575:         if($this->owner->controller instanceof CController){ 
576:             // Standard in-web-request URL generation
577: 
578:             if ($route === '') {
579:                 $route = $this->owner->controller->getId() . '/' . 
580:                     $this->owner->controller->getAction()->getId();
581:             } elseif (strpos($route, '/') === false) {
582:                 $route = $this->owner->controller->getId() . '/' . $route;
583:             }
584:             if ($route[0] !== '/' && ($module = $this->owner->controller->getModule()) !== null) {
585:                 $route = $module->getId() . '/' . $route;
586:             }
587:             $requestUrl = $this->owner->getUrlManager()->createUrlWithoutBase($route, $params);
588:             return rtrim($this->externalAbsoluteBaseUrl,'/') . $requestUrl;
589:                 
590:         }else{ // Offline URL generation
591:             return rtrim($this->externalAbsoluteBaseUrl,'/') .
592:                 (YII_UNIT_TESTING ? '/index-test.php/' : '/index.php/').
593:                 trim($route, '/').'?'.http_build_query($params, '', '&');
594:         }
595:     }
596: 
597:     /**
598:      * Magic getter for {@link absoluteBaseUrl}; in the case that web request data
599:      * isn't available, it uses a config file.
600:      *
601:      * @return type
602:      */
603:     public function getAbsoluteBaseUrl(){
604:         if(!isset($this->_absoluteBaseUrl)){
605:             if(ResponseUtil::isCli()){
606:                 // It's assumed that in this case, we're dealing with (for example)
607:                 // a cron script that sends emails and has to generate URLs. It
608:                 // needs info about how to access the CRM from the outside...
609:                 $this->_absoluteBaseUrl = '';
610:                 if($this->contEd('pro')
611:                         && $this->settings->externalBaseUrl
612:                         && $this->settings->externalBaseUri){
613:                     // Use the base URL from "public info settings" since it's
614:                     // available:
615:                     $this->_absoluteBaseUrl = $this->settings->externalBaseUrl.$this->settings->externalBaseUri;
616:                 }else if($file = realpath($this->owner->basePath.'/../webConfig.php')){
617:                     // Use the web API config file to construct the URL (our
618:                     // last hope)
619:                     include($file);
620:                     if(isset($url))
621:                         $this->_absoluteBaseUrl = $url;
622:                 } else {
623:                     // There's nothing left we can legitimately do and have it
624:                     // work correctly! Make something up.
625:                     $this->_absoluteBaseUrl = 'http://localhost';
626:                 }
627:             }else{
628:                 $this->_absoluteBaseUrl = $this->owner->getBaseUrl (true);
629:             }
630:         }
631:         return $this->_absoluteBaseUrl;
632:     }
633: 
634:     /**
635:      * Getter for {@link admin}
636:      */
637:     public function getSettings() {
638:         if(!isset($this->_settings)) {
639:             $this->cryptInit();
640:             $this->_settings = CActiveRecord::model('Admin')->findByPk(1);
641:         }
642:         return $this->_settings;
643:     }
644: 
645:     /**
646:      * Getter for {@link edition}
647:      *
648:      * @return string
649:      */
650:     public function getEdition() {
651:         if(!isset($this->_edition)){
652:             if(YII_DEBUG){
653:                 switch(PRO_VERSION) {
654:                     case 1:
655:                         $this->_edition = 'pro';
656:                         break;
657:                     case 2:
658:                         $this->_edition = 'pla';
659:                         break;
660:                     default:
661:                         $this->_edition = 'opensource';
662:                 }
663:             }else{
664:                 $this->_edition = 'opensource';
665:                 foreach(array('pla', 'pro') as $ed){
666:                     $logo = "images/x2engine_crm_$ed.png";
667:                     $logoPath = implode(DIRECTORY_SEPARATOR, array(
668:                         $this->owner->basePath,
669:                         '..',
670:                         FileUtil::rpath($logo)
671:                     ));
672:                     if(file_exists($logoPath)){
673:                         if(md5_file($logoPath) == self::$_logoHashes[$ed]){
674:                             $this->_edition = $ed;
675:                             break;
676:                         }
677:                     }
678:                 }
679:             }
680:         }
681:         return $this->_edition;
682:     }
683: 
684:     /**
685:      * Returns the edition hierarchy defined in the static configuration.
686:      *
687:      * @return type
688:      */
689:     public function getEditionHierarchy() {
690:         if(!isset(self::$_editions)) {
691:             self::$_editions = require(implode(DIRECTORY_SEPARATOR,array(
692:                 Yii::app()->basePath,
693:                 'data',
694:                 'editionHierarchy.php'
695:             )));
696:         }
697:         return self::$_editions;
698:     }
699: 
700:     /**
701:      * Returns editions "contained" by the app's current edition
702:      */
703:     public function getEditions() {
704:         return array_filter($this->editionHierarchy[$this->getEdition()]);
705:     }
706: 
707:     /**
708:      * Returns the name of the software edition.
709:      */
710:     public function getEditionLabel($addPrefix = false) {
711:         $labels = $this->getEditionLabels($addPrefix);
712:         return $labels[$this->getEdition()];
713:     }
714: 
715:     public function getEditionLabels($addPrefix = false) {
716:         $prefix = $addPrefix?'X2CRM ':'';
717:         return array(
718:             'opensource' => $prefix.'Open Source Edition',
719:             'pro' => $prefix.'Professional Edition',
720:             'pla' => $prefix.'Platinum Edition'
721:         );
722:     }
723: 
724:     /**
725:      * @return string url of favicon image file for the current version
726:      */
727:     public function getFavIconUrl () {
728:         $baseUrl = Yii::app()->clientScript->baseUrl;
729:         return $baseUrl.'/images/favicon.ico';
730:     }
731: 
732:     /**
733:      * @return string url of login logo image file for the current version
734:      */
735:     public function getLoginLogoUrl () {
736:         $baseUrl = Yii::app()->clientScript->baseUrl;
737:         return $baseUrl.'/images/x2engine.png';
738:     }
739: 
740:     public function getExternalAbsoluteBaseUrl(){
741:         if(!isset($this->_externalAbsoluteBaseUrl) || YII_UNIT_TESTING){
742:             $this->_externalAbsoluteBaseUrl = $this->externalWebDomain . $this->externalWebRoot;
743:         }
744:         return $this->_externalAbsoluteBaseUrl;
745:     }
746:     
747:     public function getExternalWebRoot() {
748:         if (!isset($this->_externalWebRoot) || YII_UNIT_TESTING) {
749:             $eabu = $this->settings->externalBaseUri;
750:             $this->_externalWebRoot = $eabu ? $eabu : $this->owner->baseUrl;
751:         }
752:         return (strpos($this->_externalWebRoot, '/') !== 0) ? '/' . $this->_externalWebRoot
753:                     : $this->_externalWebRoot;
754:     }
755: 
756:     /**
757:      * Resolves the public-facing absolute base url.
758:      *
759:      * @return type
760:      */
761:     public function getExternalWebDomain() {
762:         if (!isset($this->_externalWebDomain) || YII_UNIT_TESTING) {
763:             $eabu = $this->settings->externalBaseUrl;
764:             $this->_externalWebDomain = $eabu ? $eabu : $this->owner->request->getHostInfo();
765:         }
766:         return $this->_externalWebDomain;
767:     }
768: 
769:     /**
770:      * "isGuest" wrapper that can be used from CLI
771:      *
772:      * Used in biz rules for RBAC items in place of Yii::app()->user->isGuest for
773:      * the reason that Yii::app()->user is meaningless at the command line
774:      * @return type
775:      */
776:     public function getIsUserGuest() {
777:         if(php_sapi_name() == 'cli') {
778:             return false;
779:         } else {
780:             return $this->owner->user->isGuest;
781:         }
782:     }
783: 
784:     /**
785:      * Substitute user ID magic getter.
786:      *
787:      * If the user has already been looked up or set, method will defer to its
788:      * value for id. Defers to the value of id in {@link suModel}.
789:      * @return type
790:      */
791:     public function getSuID(){
792:         if(!isset($this->_suID) || isset($this->_suModel)){
793:             if(isset($this->_suModel)){
794:                 $this->_suID = (integer) $this->_suModel->id;
795:             }elseif($this->isInSession){
796:                 $this->_suID = (integer) $this->owner->user->getId();
797:             }elseif(php_sapi_name() == 'cli'){
798:                 // Assume admin
799:                 $this->_suID = 1;
800:             }else{
801:                 // Assume nothing/treat as guest
802:                 $this->_suID = null;
803:             }
804:         }
805:         return $this->_suID;
806:     }
807: 
808:     /**
809:      * Shortcut method for ascertaining if a user session is available
810:      * @return type
811:      */
812:     public function getIsInSession(){
813:         if(!isset($this->_isInSession)){
814:             $app = $this->owner;
815:             if($app instanceof CConsoleApplication) {
816:                 $this->_isInSession = false;
817:             } elseif(!$app->params->hasProperty('noSession')){
818:                 $this->_isInSession = true;
819:             }else{
820:                 if(!isset(Yii::app()->user) || 
821:                     Yii::app()->user instanceof X2NonWebUser ||
822:                     Yii::app()->user->isGuest){
823: 
824:                     $app->params->noSession = true;
825:                 }
826:                 $this->_isInSession = !$app->params->noSession;
827:             }
828:         }
829:         return $this->_isInSession;
830:     }
831: 
832:     /**
833:      * Returns the lock status of the application.
834:      * @return boolean
835:      */
836:     public function getLocked() {
837:         if(!isset($this->_locked)){
838:             $file = $this->lockFile;
839:             if(!file_exists($file))
840:                 return false;
841:             $this->_locked = (int) trim(file_get_contents($file));
842:         }
843:         return $this->_locked;
844:     }
845: 
846:     /**
847:      * Returns the path to the application lock file
848:      * @return type
849:      */
850:     public function getLockFile() {
851:         return implode(DIRECTORY_SEPARATOR,array(Yii::app()->basePath,'runtime','app.lock'));
852:     }
853: 
854:     /**
855:      * Lock the application (non-administrative users cannot use it).
856:      *
857:      * If the value evaluates to false, the application will be unlocked.
858:      *
859:      * @param type $value
860:      */
861:     public function setLocked($value) {
862:         $this->_locked = $value;
863:         $file = $this->lockFile;
864:         if($value == false && file_exists($file)) {
865:             unlink($file);
866:         } elseif($value !== false) {
867:             file_put_contents($this->lockFile,$value);
868:         }
869: 
870:     }
871: 
872:     /**
873:      * Substitute user model magic getter.
874:      *
875:      * @return User
876:      */
877:     public function getSuModel(){
878:         if(!isset($this->_suModel)){
879:             if($this->isInSession)
880:                 $this->_suID == $this->getOwner()->getUser()->getId();
881:             $this->_suModel = User::model()->findByPk($this->getSuID());
882:         }
883:         return $this->_suModel;
884:     }
885: 
886:     /**
887:      * Substitute user name getter.
888:      *
889:      * This is intended to be safer than suModel->userName insofar as it defaults
890:      * to "Guest" if no name/session has yet been established. It is expected that
891:      * in console commands, API requests and unit testing, the {@link suModel}
892:      * property be set as desired, so that this does not evaluate to "Guest"
893:      */
894:     public function getSuName(){
895:         if($this->getIsInSession()) {
896:             return $this->owner->user->getName();
897:         }else{
898:             if(!isset($this->_suModel)){
899:                 return 'Guest';
900:             }else{
901:                 return $this->_suModel->username;
902:             }
903:         }
904:     }
905:     
906:     /**
907:      * Magic setter for substitute user model
908:      * @param User $user
909:      */
910:     public function setSuModel(User $user){
911:         $this->_suModel = $user;
912:         if($user->id !== null)
913:             $this->setUserAccessParameters($user->id);
914:     }
915: 
916:     /**
917:      * Adds parameters that are used to determine user access
918:      * @param type $userId
919:      */
920:     private function setUserAccessParameters($userId) {
921:         $this->owner->params->groups = Groups::getUserGroups($userId);
922:         $this->owner->params->roles = Roles::getUserRoles($userId);
923:         $this->owner->params->isAdmin = $userId !== null
924:                 ? $this->owner->authManager->checkAccess('AdminIndex', $userId)
925:                 : false; 
926:     }
927: 
928:     /**
929:      * Import all directories that are used system-wide.
930:      */
931:     public function importDirectories(){
932:         Yii::import('application.models.*');
933:         Yii::import('application.controllers.X2Controller');
934:         Yii::import('application.controllers.x2base');
935:         Yii::import('application.components.*');
936:         Yii::import('application.components.formatters.*');
937:         Yii::import('application.components.X2GridView.*');
938:         Yii::import('application.components.X2Settings.*');
939:         Yii::import('application.components.publisher.*');
940:         Yii::import('application.components.recordConversion.*');
941:         Yii::import('application.components.validators.*');
942:         Yii::import('application.components.sortableWidget.*');
943:         Yii::import('application.components.sortableWidget.profileWidgets.*');
944:         Yii::import('application.components.sortableWidget.recordViewWidgets.*');
945:          
946:         Yii::import('application.components.filters.*');
947:         Yii::import('application.components.util.*');
948:         Yii::import('application.components.permissions.*');
949:         Yii::import('application.modules.media.models.Media');
950:         Yii::import('application.modules.groups.models.Groups');
951:         Yii::import('application.modules.charts.models.*');
952:         Yii::import('application.modules.charts.components.*');
953:         Yii::import('application.modules.charts.ChartsModule');
954: 
955:         $modules = $this->owner->modules;
956:         $arr = array();
957:         $modulePath = implode(DIRECTORY_SEPARATOR,array(
958:             $this->owner->basePath,
959:             'modules'
960:         ));
961:         foreach(scandir($modulePath) as $module){
962:             $regScript = implode(DIRECTORY_SEPARATOR,array(
963:                 $modulePath,
964:                 $module,
965:                 'register.php'
966:             ));
967:             if(file_exists($regScript)){
968:                 $arr[$module] = ucfirst($module);
969:                 $thisModulePath = "application.modules.$module";
970:                 Yii::import("$thisModulePath.models.*");
971:                 if(is_dir(Yii::getPathOfAlias($thisModulePath).DIRECTORY_SEPARATOR.'components')) {
972:                     Yii::import("$thisModulePath.components.*");
973:                 }
974:             }
975:         }
976:         foreach($arr as $key => $module){
977:             $record = Modules::model()->findByAttributes(array('name' => $key));
978:             if(isset($record))
979:                 $modules[] = $key;
980:         }
981:         $this->owner->setModules($modules);
982:     }
983: 
984:     public function isMobileApp () {
985:         return isset ($_GET['isMobileApp']) && $_GET['isMobileApp'];
986:     }
987: 
988:     private function isPhoneGap () {
989:         return isset ($_COOKIE['isPhoneGap']) && $_COOKIE['isPhoneGap'];
990:     }
991: 
992: }
993: 
X2CRM Documentation API documentation generated by ApiGen 2.8.0