Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Download, extract and symlink the latest version of PhpStorm on Linux.
#!/usr/bin/env php
<?php
/**
* $extractPath must be writable by the user account used to launch this script
*/
$extractPath = '/opt/.PhpStorm';
$versionPage = 'http://www.jetbrains.com/phpstorm/download/index.html';
$versionPageEap = 'http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program';
$downloadPage = 'http://www.jetbrains.com/phpstorm/download/download_thanks.jsp?os=linux';
#region Functions
// get the page text - uses a cached copy if retrieved within the last 5 minutes
$getPage = function ($url) {
$file = sys_get_temp_dir() . '/phpstorm-' . dechex(crc32($url)) . '.html';
$splFileInfo = new \SplFileInfo($file);
$modified = $splFileInfo->isFile() ? $splFileInfo->getMTime() : 0;
if (time() - $modified > 300) {
file_put_contents($file, file_get_contents($url));
}
return file_get_contents($file);
};
$getInstalledVersion = function () use ($extractPath) {
$version = null;
$file = "$extractPath/default/build.txt";
if (file_exists($file)) {
$version = preg_replace('/^PS-/', '', trim(file_get_contents($file)));
}
return $version;
};
$getVersion = function ($pattern, $versionPage) use ($getPage) {
preg_match($pattern, $getPage($versionPage), $match);
return $match ? $match : null;
};
$getLatestVersion = function () use ($getVersion, $versionPage) {
if (!($match = $getVersion('/Build:.{1,500}?>(\d+(?:\.\d+)?)/sm', $versionPage))) {
fwrite(STDERR, "Failed to detect the latest version\n");
exit(1);
}
return $match[1];
};
$getLatestVersionEap = function (&$downloadLink = null) use ($getVersion, $versionPageEap) {
$match = $getVersion('#["\']((?:ftp|https?)://[^"\']+-EAP-(\d+(?:\.\d+)?)\.tar\.gz[^"\']*)#', $versionPageEap);
$downloadLink = $match[1];
return $match[2];
};
$getDownloadLink = function () use ($getPage, $downloadPage) {
if (!preg_match('#["\']((?:ftp|https?)://[^"\']+\.tar\.gz[^"\']*)#', $getPage($downloadPage), $match)) {
fwrite(STDERR, "Failed to detected the latest version\n");
exit(1);
}
return $match[1];
};
$downloadFile = function ($url, $destination, $callback = null, &$info = array()) {
$hnd = fopen($destination, 'wb');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $hnd);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
if ($callback) {
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $bytes) use ($callback, $hnd) {
return call_user_func($callback, $ch, $bytes, $hnd);
});
}
curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
fclose($hnd);
if ($info['http_code'] === 200) {
$filesize = filesize($destination);
} else {
if (file_exists($destination)) {
unlink($destination);
}
$filesize = -1;
}
return $filesize;
};
$downloadFileWithProgress = function (
$url,
$destination,
$progressCallback = null,
$interval = 100,
&$info = array()) use ($downloadFile) {
if (function_exists('pcntl_fork')) {
$key = ftok(__FILE__, 't');
$shm = @shm_attach($key, 102400, 0640);
} else {
$key = null;
$shm = null;
}
if ($shm) {
shm_put_var($shm, 0, null); // waiting for the child to finish
shm_put_var($shm, 1, -1); // the filesize of the remote target
shm_put_var($shm, 2, -1); // the number or bytes written
$pid = pcntl_fork();
if ($pid === 0) { // child fork
$pid = posix_getpid();
try {
// perform a HEAD request to get the size of the remote file
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
$info = curl_getinfo($ch);
$contentLength = $info['download_content_length'];
shm_put_var($shm, 1, $contentLength);
// start the download
$written = -1;
$downloadFile($url, $destination, function ($ch, $bytes, $hnd) use ($shm, &$written) {
$length = fwrite($hnd, $bytes);
$written = $written ? $written + $length : $length;
shm_put_var($shm, 2, $written);
return $length;
}, $info);
shm_put_var($shm, 2, $written);
} catch (Exception $e) {
print_r($e);
}
shm_put_var($shm, 0, $info); // child finished
posix_kill($pid, SIGKILL); // kill the child
}
$last = -1;
while (($info = shm_get_var($shm, 0)) === null) {
if ($progressCallback) {
$total = shm_get_var($shm, 1);
$written = shm_get_var($shm, 2);
if ($written !== $last) {
call_user_func($progressCallback, $written, $total, $destination);
$last = $written;
}
}
usleep($interval * 1000);
}
$total = shm_get_var($shm, 1);
$written = shm_get_var($shm, 2);
shm_remove($shm);
if ($progressCallback) {
call_user_func($progressCallback, $written, $total, $destination);
}
} else {
// synchronous fallback if pcntl is not available or unable to allocate shared memory
$written = $downloadFile($url, $destination, null, $info);
}
return $written;
};
$extract = function ($archive, $destination) {
$p = new PharData($archive);
$success = $p->extractTo($destination);
return $success;
};
$do = function ($function, $args, $text, $error) {
fwrite(STDOUT, "$text\n");
if (!call_user_func_array($function, $args)) {
fwrite(STDERR, "$error\n");
exit(1);
}
};
#endregion
$installedVersion = $getInstalledVersion() ?: 'n/a';
fwrite(STDOUT, "Detecting installed version: $installedVersion\n");
fwrite(STDOUT, "Detecting latest version: ");
$latestVersion = $getLatestVersionEap($downloadLink) ?: $getLatestVersion();
fwrite(STDOUT, "$latestVersion\n");
if (version_compare($latestVersion, $installedVersion) !== 1) {
fwrite(STDOUT, "No action required\n");
exit(0);
}
fwrite(STDOUT, "Update required\n");
$downloadName = "PhpStorm-$latestVersion.tar.gz";
$downloadPath = getcwd() . "/$downloadName";
if (!file_exists($downloadPath) || filesize($downloadPath) === 0) {
fwrite(STDOUT, "Finding the download link: ");
$downloadLink || $downloadLink = $getDownloadLink();
fwrite(STDOUT, "$downloadLink\n");
fwrite(STDOUT, "Downloading target: '$downloadPath'\n");
// download the file and display a progress indicator
$info = array();
$downloadFileWithProgress($downloadLink, $downloadPath, function ($written, $total, $path) {
$pct = number_format(100 * ($written / $total), 2);
$written = number_format($written / 1024, 0);
$total = number_format($total / 1024, 0);
fwrite(STDOUT, "\r$written/$total kB [$pct%]");
}, 100, $info);
$bytes = number_format($info['size_download'] / 1024, 0);
$time = number_format($info['total_time'], 2);
fwrite(STDOUT, "\rDownloaded $bytes kB in $time seconds\n");
} else {
fwrite(STDOUT, "The file '$downloadName' exists skipping download\n");
}
$temp = "$extractPath/" . substr($downloadName, 0, -7);
$dest = "$extractPath/$latestVersion";
$link = "$extractPath/default";
foreach (array($dest, $temp) as $path) {
if (is_dir($path) || !is_writable($extractPath)) {
fwrite(STDERR, "Cannot create folder '$path'\n");
exit(1);
}
}
$do($extract, array($downloadPath, $extractPath),
"Extracting archive to '$temp'",
"Failed to extract the archive");
$do('rename', array($temp, $dest),
"Renaming '$temp' -> '$dest'",
"Failed to rename the directory");
if (is_link($link)) {
fwrite(STDOUT, "Removing existing symlink '$link'\n");
unlink($link);
}
$do('symlink', array($dest, $link),
"Creating symlink '$link' -> '$dest'",
"Failed to create the symlink");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.