3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2013
35 class CRM_Utils_VersionCheck
{
37 LATEST_VERSION_AT
= 'http://latest.civicrm.org/stable.php',
38 // timeout for when the connection or the server is slow
40 // relative to $civicrm_root
41 LOCALFILE_NAME
= 'civicrm-version.php',
42 // relative to $config->uploadDir
43 CACHEFILE_NAME
= 'latest-version-cache.txt',
44 // cachefile expiry time (in seconds) - a week
45 CACHEFILE_EXPIRE
= 604800;
48 * We only need one instance of this object, so we use the
49 * singleton pattern and cache the instance in this variable
54 static private $_singleton = NULL;
57 * The version of the current (local) installation
61 public $localVersion = NULL;
64 * The latest version of CiviCRM
68 public $latestVersion = NULL;
75 protected $stats = array();
82 function __construct() {
84 $config = CRM_Core_Config
::singleton();
86 $localfile = $civicrm_root . DIRECTORY_SEPARATOR
. self
::LOCALFILE_NAME
;
87 $cachefile = $config->uploadDir
. self
::CACHEFILE_NAME
;
89 if (file_exists($localfile)) {
90 require_once ($localfile);
91 if (function_exists('civicrmVersion')) {
92 $info = civicrmVersion();
93 $this->localVersion
= $info['version'];
96 if ($config->versionCheck
) {
97 $expiryTime = time() - self
::CACHEFILE_EXPIRE
;
99 // if there's a cachefile and it's not stale use it to
100 // read the latestVersion, else read it from the Internet
101 if (file_exists($cachefile) && (filemtime($cachefile) > $expiryTime)) {
102 $this->latestVersion
= file_get_contents($cachefile);
105 $siteKey = md5(defined('CIVICRM_SITE_KEY') ? CIVICRM_SITE_KEY
: '');
107 $this->stats
= array(
108 'hash' => md5($siteKey . $config->userFrameworkBaseURL
),
109 'version' => $this->localVersion
,
110 'uf' => $config->userFramework
,
111 'lang' => $config->lcMessages
,
112 'co' => $config->defaultContactCountry
,
113 'ufv' => $config->userFrameworkVersion
,
114 'PHP' => phpversion(),
115 'MySQL' => CRM_CORE_DAO
::singleValueQuery('SELECT VERSION()'),
119 $this->payProcStats();
120 $this->entityStats();
121 $this->extensionStats();
123 // Get the latest version and send site info
127 if ($this->latestVersion
) {
128 $fp = @fopen
($cachefile, 'w');
130 if (CRM_Core_Permission
::check('administer CiviCRM')) {
131 CRM_Core_Session
::setStatus(
132 ts('Unable to write file') . ":$cachefile<br />" . t('Please check your system file permissions.'),
133 ts('File Error'), 'error');
137 fwrite($fp, $this->latestVersion
);
145 * Static instance provider
147 * Method providing static instance of CRM_Utils_VersionCheck,
148 * as in Singleton pattern
150 * @return CRM_Utils_VersionCheck
152 static function &singleton() {
153 if (!isset(self
::$_singleton)) {
154 self
::$_singleton = new CRM_Utils_VersionCheck();
156 return self
::$_singleton;
160 * Get the latest version number if it's newer than the local one
162 * @return string|null
163 * Returns the newer version's number or null if the versions are equal
165 public function newerVersion() {
166 if ($this->latestVersion
) {
167 $local = array_pad(explode('.', $this->localVersion
), 3, 0);
168 $latest = array_pad(explode('.', $this->latestVersion
), 3, 0);
170 for ($i = 0; $i < 3; $i++
) {
171 if ($local[$i] > $latest[$i]) {
174 elseif ($local[$i] < $latest[$i]) {
175 return $this->latestVersion
;
183 * Alert the site admin of new versions of CiviCRM
184 * Show the message once a day
186 public function versionAlert() {
187 if (CRM_Core_Permission
::check('administer CiviCRM') && $this->newerVersion()) {
188 $session = CRM_Core_Session
::singleton();
189 if ($session->timer('version_alert', 24 * 60 * 60)) {
190 $msg = ts('A newer version of CiviCRM is available: %1', array(1 => $this->latestVersion
))
191 . '<br />' . ts('<a href="%1">Download Now</a>', array(1 => 'http://civicrm.org/download'));
192 $session->setStatus($msg, ts('Update Available'));
198 * Get active payment processor types
200 private function payProcStats() {
201 $dao = new CRM_Financial_DAO_PaymentProcessor
;
206 // Get title and id for all processor types
207 $ppTypeNames = CRM_Core_PseudoConstant
::paymentProcessorType();
209 while ($dao->fetch()) {
210 $ppTypes[] = $ppTypeNames[$dao->payment_processor_type_id
];
212 // add the .-separated list of the processor types
213 $this->stats
['PPTypes'] = implode(',', array_unique($ppTypes));
218 * Fetch counts from entity tables
219 * Add info to the 'entities' array
221 private function entityStats() {
223 'CRM_Activity_DAO_Activity' => 'is_test = 0',
224 'CRM_Case_DAO_Case' => 'is_deleted = 0',
225 'CRM_Contact_DAO_Contact' => 'is_deleted = 0',
226 'CRM_Contact_DAO_Relationship' => NULL,
227 'CRM_Campaign_DAO_Campaign' => NULL,
228 'CRM_Contribute_DAO_Contribution' => 'is_test = 0',
229 'CRM_Contribute_DAO_ContributionPage' => 'is_active = 1',
230 'CRM_Contribute_DAO_ContributionProduct' => NULL,
231 'CRM_Contribute_DAO_Widget' => 'is_active = 1',
232 'CRM_Core_DAO_Discount' => NULL,
233 'CRM_Price_DAO_SetEntity' => NULL,
234 'CRM_Core_DAO_UFGroup' => 'is_active = 1',
235 'CRM_Event_DAO_Event' => 'is_active = 1',
236 'CRM_Event_DAO_Participant' => 'is_test = 0',
237 'CRM_Friend_DAO_Friend' => 'is_active = 1',
238 'CRM_Grant_DAO_Grant' => NULL,
239 'CRM_Mailing_DAO_Mailing' => 'is_completed = 1',
240 'CRM_Member_DAO_Membership' => 'is_test = 0',
241 'CRM_Member_DAO_MembershipBlock' => 'is_active = 1',
242 'CRM_Pledge_DAO_Pledge' => 'is_test = 0',
243 'CRM_Pledge_DAO_PledgeBlock' => NULL,
245 foreach ($tables as $daoName => $where) {
248 $dao->whereAdd($where);
250 $short_name = substr($daoName, strrpos($daoName, '_') +
1);
251 $this->stats
['entities'][] = array(
252 'name' => $short_name,
253 'size' => $dao->count(),
259 * Fetch stats about enabled components/extensions
260 * Add info to the 'extensions' array
262 private function extensionStats() {
264 $config = CRM_Core_Config
::singleton();
265 foreach ($config->enableComponents
as $comp) {
266 $this->stats
['extensions'][] = array(
267 'name' => 'org.civicrm.component.' . strtolower($comp),
269 'version' => $this->stats
['version'],
272 // Contrib extensions
273 $mapper = CRM_Extension_System
::singleton()->getMapper();
274 $dao = new CRM_Core_DAO_Extension();
276 while ($dao->fetch()) {
277 $info = $mapper->keyToInfo($dao->full_name
);
278 $this->stats
['extensions'][] = array(
279 'name' => $dao->full_name
,
280 'enabled' => $dao->is_active
,
281 'version' => isset($info->version
) ?
$info->version
: NULL,
287 * Send the request to civicrm.org
288 * Set timeout and suppress errors
290 private function pingBack() {
291 ini_set('default_socket_timeout', self
::CHECK_TIMEOUT
);
295 'header' => 'Content-type: application/x-www-form-urlencoded',
296 'content' => http_build_query($this->stats
),
299 $ctx = stream_context_create($params);
300 $this->latestVersion
= @file_get_contents
(self
::LATEST_VERSION_AT
, FALSE, $ctx);
301 if (!preg_match('/^\d+\.\d+\.\d+$/', $this->latestVersion
)) {
302 $this->latestVersion
= NULL;
304 ini_restore('default_socket_timeout');