Jump to content
X2Community Forums

How to Update to a New Version

Recommended Posts

EDIT: Updating this post to reflect new information as of December 19, 2012. Please note that any posts below from previous dates DO NOT reflect correct information.

The preferred method of updating X2CRM is using our built in automatic updater. Automatic updates take a little bit of time to test and as such our release schedule tends to be that we release the new version for download in the afternoon or at night and then the automatic update is available the next day. Upon login as admin you will be prompted to update your software. Follow the instructions provided and it should be a seamless experience (as of this writing we have tested from updating version 1.3 to 2.5 and it appears to work).

Please note that your server will need to have the allow_url_fopen parameter in php.ini set to 1. You can check this by calling phpinfo(); on any script on your web page. All files will then be downloaded to the proper locations, any SQL queries required for database changes will be run, and old files no longer used will be deleted.

If you do not want to use the automatic updater, please follow the steps below. Please note that this method will not be able to recover all data (social posts, form versions, anything that doesn't show up in your list of modules, etc.) and as such the automatic updater is highly recommended. You can simply export the SQL to put back in instead of using our exporter, but columns may have changed in the new version.

Here's some step by step tips to make sure you save your data:

  • Log in to the Admin account and go to the Admin tab.
  • Click "Export Data" and select all the modules you want to export data from. Download the generated file after the export is complete.
  • Delete any custom modules you have made using the Admin tab, you'll need to re-create them after this process.
  • Download the new version of X2CRM and extract the Zip file.
  • Delete your previous installation of X2CRM from your server.
  • Upload the new version of X2CRM to your server/local machine and install.
  • Log in as Admin
  • Re-create any custom modules you had to ensure import compatibility, if a module is not found, the records for that module simply will not be imported.
  • On the Admin tab click "Import Data" and upload the file from before.

If you run into any issues or need any help, please feel free to post here and we will assist you to the best of our ability.


Edited by X2Jake
Updated information. 12/19/12
Link to post
Share on other sites
  • 4 weeks later...

Hey there!


I'll be looking into the issue shortly. In the mean time, if you look at the URL for the application, delete everything pas "index.php" and then replace "index.php" with "updater.php" and the script should run just fine. Let me know if you have any more issues.



Link to post
Share on other sites

Alright Frax, two things I need to look at to try to figure out what's going on.


If you could ping/traceroute these two addresses: www.x2planet.com and www.x2base.com and give me the results. These are our update servers, and if you can't connect to them there might be an issue. However, it may simply be a timeout issue (we set the timeout very low in case a server wasn't responding).


Would you mind posting the mile-long error on here so I can take a look and try to reproduce/fix it?

Link to post
Share on other sites

Hi Jake,


Here are the ping results:


ping www.x2planet.com

PING www.x2planet.com ( 56(84) bytes of data.

64 bytes from colo-63-249-66-66.static.cruzio.com ( icmp_req=1 ttl=51 time=149 ms

64 bytes from colo-63-249-66-66.static.cruzio.com ( icmp_req=2 ttl=51 time=149 ms

64 bytes from colo-63-249-66-66.static.cruzio.com ( icmp_req=3 ttl=51 time=149 ms

64 bytes from colo-63-249-66-66.static.cruzio.com ( icmp_req=4 ttl=51 time=149 ms

64 bytes from colo-63-249-66-66.static.cruzio.com ( icmp_req=5 ttl=51 time=149 ms


--- www.x2planet.com ping statistics ---

5 packets transmitted, 5 received, 0% packet loss, time 4005ms

rtt min/avg/max/mdev = 149.057/149.463/149.916/0.398 ms

roadeagle starbux # ping www.x2base.com

PING www.x2base.com ( 56(84) bytes of data.

64 bytes from colo-63-249-66-67.static.cruzio.com ( icmp_req=1 ttl=52 time=149 ms

64 bytes from colo-63-249-66-67.static.cruzio.com ( icmp_req=2 ttl=52 time=149 ms

64 bytes from colo-63-249-66-67.static.cruzio.com ( icmp_req=3 ttl=52 time=148 ms


--- www.x2base.com ping statistics ---

4 packets transmitted, 3 received, 25% packet loss, time 3004ms

rtt min/avg/max/mdev = 148.957/149.333/149.999/0.649 ms


I'm in France btw :-) and the server hosting the whole thing is a pro grade dedicated server at a big provider.


Here's the login page after manually upgrading to 0.9.5 - I'm using lighttpd on a gentoo system with multiple vhosts ; each vhost has its own php.ini.




PHP Error


Cannot modify header information - headers already sent by (output started at /home/www/suncrusher.eu/htdocs/x2engine/x2base.php:1)




645 /**

646 * Redirects the browser to the specified URL.

647 * @param string $url URL to be redirected to. If the URL is a relative one, the base URL of

648 * the application will be inserted at the beginning.

649 * @param boolean $terminate whether to terminate the current application

650 * @param integer $statusCode the HTTP status code. Defaults to 302. See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html}

651 * for details about HTTP status code. This parameter has been available since version 1.0.4.

652 */

653 public function redirect($url,$terminate=true,$statusCode=302)

654 {

655 if(strpos($url,'/')===0)

656 $url=$this->getHostInfo().$url;

657 header('Location: '.$url, true, $statusCode);

658 if($terminate)

659 Yii::app()->end();

660 }


662 /**

663 * Returns the user preferred language.

664 * The returned language ID will be canonicalized using {@link CLocale::getCanonicalID}.

665 * This method returns false if the user does not have language preference.

666 * @return string the user preferred language.

667 */

668 public function getPreferredLanguage()

669 {



Stack Trace



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/CHttpRequest.php(657): header("Location: http://www.suncrusher.eu/x2engine/index.php/site/whats...", true, 302)


652 */

653 public function redirect($url,$terminate=true,$statusCode=302)

654 {

655 if(strpos($url,'/')===0)

656 $url=$this->getHostInfo().$url;

657 header('Location: '.$url, true, $statusCode);

658 if($terminate)

659 Yii::app()->end();

660 }


662 /**



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/CController.php(1005): CHttpRequest->redirect("/x2engine/index.php/site/whatsNew", true, 302)


1000 if(is_array($url))

1001 {

1002 $route=isset($url[0]) ? $url[0] : '';

1003 $url=$this->createUrl($route,array_splice($url,1));

1004 }

1005 Yii::app()->getRequest()->redirect($url,$terminate,$statusCode);

1006 }


1008 /**

1009 * Refreshes the current page.

1010 * The effect of this method call is the same as user pressing the



– /home/www/suncrusher.eu/htdocs/x2engine/protected/controllers/SiteController.php(510): CController->redirect(array("site/whatsNew"))


505 }

506 }else{

507 Yii::app()->session['alertUpdate']=false;

508 }

509 if(empty($profile->startPage)) {

510 $this->redirect(array('site/whatsNew'));

511 } else {

512 $file = Yii::app()->file->set('protected/controllers/'.ucfirst($profile->startPage).'Controller.php');

513 if($file->exists)

514 $this->redirect(array(ucfirst($profile->startPage).'/index'));

515 else {



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/actions/CInlineAction.php(50): SiteController->actionIndex()


45 $controller=$this->getController();

46 $method=new ReflectionMethod($controller, $methodName);

47 if($method->getNumberOfParameters()>0)

48 return $this->runWithParamsInternal($controller, $method, $params);

49 else

50 return $controller->$methodName();

51 }


53 }



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/CController.php(300): CInlineAction->runWithParams(array())


295 {

296 $priorAction=$this->_action;

297 $this->_action=$action;

298 if($this->beforeAction($action))

299 {

300 if($action->runWithParams($this->getActionParams())===false)

301 $this->invalidActionParams($action);

302 else

303 $this->afterAction($action);

304 }

305 $this->_action=$priorAction;



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/filters/CFilterChain.php(133): CController->runAction(CInlineAction)


128 $filter=$this->itemAt($this->filterIndex++);

129 Yii::trace('Running filter '.($filter instanceof CInlineFilter ? get_class($this->controller).'.filter'.$filter->name.'()':get_class($filter).'.filter()'),'system.web.filters.CFilterChain');

130 $filter->filter($this);

131 }

132 else

133 $this->controller->runAction($this->action);

134 }

135 } #6


– /home/www/suncrusher.eu/htdocs/x2engine/protected/controllers/SiteController.php(66): CFilterChain->run()


61 // foreach($arr as $key=>$value){

62 // $config=ProfileChild::parseWidget($value,$key);

63 // $this->portlets[$key]=$config;

64 // }

65 }

66 $filterChain->run();

67 }


69 public function actions() {

70 return array(

71 // captcha action renders the CAPTCHA image displayed on the contact page



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/filters/CInlineFilter.php(59): SiteController->filterSetPortlets(CFilterChain)


54 * @param CFilterChain $filterChain the filter chain that the filter is on.

55 */

56 public function filter($filterChain)

57 {

58 $method='filter'.$this->name;

59 $filterChain->controller->$method($filterChain);

60 }

61 }



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/filters/CFilterChain.php(130): CInlineFilter->filter(CFilterChain)


125 {

126 if($this->offsetExists($this->filterIndex))

127 {

128 $filter=$this->itemAt($this->filterIndex++);

129 Yii::trace('Running filter '.($filter instanceof CInlineFilter ? get_class($this->controller).'.filter'.$filter->name.'()':get_class($filter).'.filter()'),'system.web.filters.CFilterChain');

130 $filter->filter($this);

131 }

132 else

133 $this->controller->runAction($this->action);

134 }

135 } #9


– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/CController.php(283): CFilterChain->run()


278 $this->runAction($action);

279 else

280 {

281 $priorAction=$this->_action;

282 $this->_action=$action;

283 CFilterChain::create($this,$action,$filters)->run();

284 $this->_action=$priorAction;

285 }

286 }


288 /**



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/CController.php(257): CController->runActionWithFilters(CInlineAction, array("setPortlets"))


252 {

253 if(($parent=$this->getModule())===null)

254 $parent=Yii::app();

255 if($parent->beforeControllerAction($this,$action))

256 {

257 $this->runActionWithFilters($action,$this->filters());

258 $parent->afterControllerAction($this,$action);

259 }

260 }

261 else

262 $this->missingAction($actionID);



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/CWebApplication.php(328): CController->run("")


323 {

324 list($controller,$actionID)=$ca;

325 $oldController=$this->_controller;

326 $this->_controller=$controller;

327 $controller->init();

328 $controller->run($actionID);

329 $this->_controller=$oldController;

330 }

331 else

332 throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',

333 array('{route}'=>$route===''?$this->defaultController:$route)));



– /home/www/suncrusher.eu/htdocs/x2engine/framework/web/CWebApplication.php(121): CWebApplication->runController("")


116 foreach(array_splice($this->catchAllRequest,1) as $name=>$value)

117 $_GET[$name]=$value;

118 }

119 else

120 $route=$this->getUrlManager()->parseUrl($this->getRequest());

121 $this->runController($route);

122 }


124 /**

125 * Registers the core application components.

126 * This method overrides the parent implementation by registering additional core components.



– /home/www/suncrusher.eu/htdocs/x2engine/framework/base/CApplication.php(155): CWebApplication->processRequest()


150 */

151 public function run()

152 {

153 if($this->hasEventHandler('onBeginRequest'))

154 $this->onBeginRequest(new CEvent($this));

155 $this->processRequest();

156 if($this->hasEventHandler('onEndRequest'))

157 $this->onEndRequest(new CEvent($this));

158 }


160 /**



– /home/www/suncrusher.eu/htdocs/x2engine/index.php(59): CApplication->run()


54 defined('YII_DEBUG') or define('YII_DEBUG',true);

55 // specify how many levels of call stack should be shown in each log message

56 defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);


58 require_once($yii);

59 Yii::createWebApplication($config)->run();


2011-11-08 22:16:54 lighttpd/1.4.29 Yii Framework/1.1.7


Link to post
Share on other sites

Alright so here's my thinking:


1) It's very strange that your updater isn't working. Check your PHP.ini file(s) and look for the "allow_url_fopen" variable and make sure it's set to 1.


2) As for that PHP error, I think it might be something incredibly silly. I am fairly sure a space accidentally got in front of the opening PHP tag of x2base in this build. Depending on your server config then, the headers will get mad at that space. Try deleting it and see if it fixes the issue, if not, I'll keep looking into it and see what else I can dig up in the meantime.



Link to post
Share on other sites

Hey there,


1) allow_url_fopen = on did the trick. Updater message works fine.


2) Clicking the update button gives:


Failed SQL query: CREATE TABLE x2_notifications( id INT NOT NULL AUTO_INCREMENT primary key, text TEXT, record VARCHAR(250), user VARCHAR(100), viewed INT, createDate INT) COLLATE = utf8_general_ci

Update failed


Sorry to be a pain in the neck.



Link to post
Share on other sites

Not a problem at all. So the issue is that when you ran the install manually it created all the tables. When you use the auto-updater, it will try to create those tables, fail, and then cancel the update and restore your files. The easiest fix is to delete the tables x2_notifications and x2_criteria from your database and re-run the installer. The updater is something we're still putting more work into because it needs to be one of the most solid features.



Link to post
Share on other sites
  • 3 weeks later...

Hey there,


Me again ... Trying to update to latest version 0.9.7 fails with following error :


Failed SQL query: ALTER TABLE x2_profile ADD COLUMN showSocialMedia TINYINT DEFAULT 0

Update failed


Yes, I'm using the updater. Hope this helps.






"Liberty without equality is like having the right to dive into a swimming pool that has no water in it."

Link to post
Share on other sites

We just found this bug today, and it's in a few places. We posted v0.9.7.1, but this unfortunately does not contain the full fix. An automatic update will be going out later today to resolve the issue as well.


In protected/view/contacts there are 2 files that have a slight issue.


_simpleView.php and _form.php


both have a method call to ProfileChild::getSocialMedia(), a method which has been replaced to improve performance.


In _simpleView.php the first uncommented line of code (line 37, I believe) should look like:




This should be replaced with:




On _form.php, the error is in 2 places. Lines 37 and 72. Replace the first line and delete the second one and it should be fixed--this will also resolve the encoding issue.


Thanks for the bug reports as always,


Link to post
Share on other sites
  • 5 months later...

Hi, tried to update today from 1.3.1 to 1.4. The updater didn't notify me of any updates even if it's set to check at every login. I've tried to run updater.php but it reported that the available version is 1.2 and is older than my current one.


I gave up on the automatic update and I've followed the instructions for the upgrade at the beginning of this thread. I've exported my data, removed my previous installation and installed the new one. Immediately after login I've tried to import my data.


My problem is that I've had a custom module named "Appointment" which is gone with the old folders. Now, when I try to import the data, I get an error stating


include(Appointment.php) [<a href='function.include'>function.include</a>]: failed to open stream: No such file or directory


What can be done now in order to restore my data? Many thanks!

Link to post
Share on other sites



So the automatic update usually comes a day or two after the downloadable release as it takes a bit longer to set up and get going. I'm sorry you had some issues here, but I had forgotten this thread existed and it is very much out of date. I'll be updating it shortly.


To import your data, you're going to need to re-create the custom module you had or it won't be able to import properly. However, you're going to need to check your MySQL database for any tables that have lingered around from custom modules, as that may interfere with creating a new one.


Import/export functionality is going to be improved for the next release, but for the moment you have to ensure that all of your data is compatible with the configuration of X2CRM, including custom data.



Link to post
Share on other sites

I've tried to recreate the module, but I've got a message that "Table 'x2_appointment' already exists". Should I delete the table? What about the custom fields that were created in the table? Do I need to recreate them again or are they saved in the backup? The module also had some lookup fields for the contacts. Should I delete them also? Please advise.

Link to post
Share on other sites

So the installer clears out all of the x2_ tables that are installed by default, including the x2_fields table. This means you'll need to delete x2_appointments but the fields will have already been removed for you. We don't have it clear out the whole database so you can use a lower level of permissions for the app.

Link to post
Share on other sites
  • 1 month later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...