Skip to content
This repository was archived by the owner on Jan 25, 2023. It is now read-only.

7.0.0 #78

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
/phpunit.xml.dist export-ignore
/README.md export-ignore
/ruleset.xml export-ignore
/scripts export-ignore
156 changes: 156 additions & 0 deletions scripts/fetchEdgeVersions/ChangeWindows.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<?php

/**
* Fetch versions from changewindows.org
* © 2014-present CHANGEWINDOWS
*
* Disclaimer
* All trademarks mentioned are the property of their respective owners. The content generated by this script
* comes from changewindows.org and may not be accurate.
*/
class ChangeWindows
{
private static $errors = array(
'could_not_fetch_version' => 'Could not fetch current version from ChangeWindows',
'invalid_version' => 'Windows version is invalid',
'could_not_fetch_page' => 'Could not fetch page from ChangeWindows'
);

public static function fetchVersions()
{
$windowsVersions = json_decode(file_get_contents(__DIR__ . '/windowsVersions.json'), true);
if (!count($windowsVersions)) {
$currentVersion = explode('.', self::fetchCurrentVersion(), 2);
if (!isset($currentVersion[0])) {
throw new Exception(self::$errors['invalid_version']);
}
$windowsVersions = self::fetchVersion($windowsVersions, $currentVersion[0]);
self::writeWindowsVersions($windowsVersions);
} else {
reset($windowsVersions);
$firstVersion = key($windowsVersions);
end($windowsVersions);
$lastVersion = key($windowsVersions);

try {
$result = self::fetchVersion($windowsVersions, $firstVersion);
$windowsVersions = $result;
} catch (Exception $e) {
}

$windowsVersions = self::fetchVersion($windowsVersions, $lastVersion);
self::writeWindowsVersions($windowsVersions);
}
}

private static function fetchVersion($windowsVersions, $version)
{
$siblingVersions = self::fetchPage($version);
$windowsVersions[$version] = true;
self::writeWindowsVersions($windowsVersions);

if (isset($siblingVersions[0]) && !isset($windowsVersions[$siblingVersions[0]])) {
$windowsVersions = self::fetchVersion($windowsVersions, $siblingVersions[0]);
}

if (isset($siblingVersions[1]) && !isset($windowsVersions[$siblingVersions[1]])) {
$windowsVersions = self::fetchVersion($windowsVersions, $siblingVersions[1]);
}

return $windowsVersions;
}

private static function writeWindowsVersions($windowsVersions)
{
ksort($windowsVersions);
file_put_contents(__DIR__ . '/windowsVersions.json', json_encode($windowsVersions, JSON_PRETTY_PRINT));
}

private static function fetchCurrentVersion()
{
$content = file_get_contents('https://changewindows.org/filter/pc/all/current/month/true');
if (!$content) {
throw new Exception(self::$errors['could_not_fetch_version']);
}
$content = explode('class="timeline"', $content, 2);
if (!isset($content[1])) {
throw new Exception(self::$errors['could_not_fetch_version']);
}
$content = explode('build"', $content[1], 2);
if (!isset($content[1])) {
throw new Exception(self::$errors['could_not_fetch_version']);
}
preg_match("/(\d*\.\d*)<\/div>/", $content[1], $matches);
if (!isset($matches[1])) {
throw new Exception(self::$errors['could_not_fetch_version']);
}
return $matches[1];
}

private static function fetchPage($version)
{
$url = "https://changewindows.org/build/{$version}/pc";
$content = file_get_contents($url);
$siblingVersions = self::fetchSiblingVersions($content);
self::fetchEdgeVersion($content);
return $siblingVersions;
}

private static function fetchEdgeVersion($content)
{
preg_match('/<h4[^>]*> *Edge ([\d\.]*) *<\/h4>/', $content, $edge);
preg_match('/<h4[^>]*>EdgeHTML ([\d\.]*)<\/h4>/', $content, $edgeHtml);

if (isset($edge[1]) && isset($edgeHtml[1])) {
self::writeEdgeVersion($edgeHtml[1], $edge[1]);
}
return null;
}

private static function writeEdgeVersion($edgeHtml, $edge)
{
$file = __DIR__ . '/../../src/edgeVersionMap.php';
$currentVersions = require $file;
if (!isset($currentVersions[$edgeHtml])) {
$currentVersions[$edgeHtml] = $edge;
ksort($currentVersions);
$content = '';
foreach ($currentVersions as $edgeHtml => $edge) {
$content .= " '{$edgeHtml}' => '{$edge}'," . PHP_EOL;
}
$data = <<<PHP
<?php

return array(
%s
);

PHP;
file_put_contents($file, sprintf($data, trim($content)));
}
}

private static function fetchSiblingVersions($content)
{
if (!$content) {
throw new Exception(self::$errors['could_not_fetch_page']);
}
$content = explode('build-sidebar', $content, 2);
if (!isset($content[1])) {
throw new Exception(self::$errors['could_not_fetch_page']);
}
$content = explode('fa-angle-left', $content[1]);
if (!isset($content[1])) {
throw new Exception(self::$errors['could_not_fetch_page']);
}
$content = explode('fa-angle-right', $content[1]);
if (!isset($content[0])) {
throw new Exception(self::$errors['could_not_fetch_page']);
}
preg_match_all("/> *(\d+) *</", $content[0], $matches);
if (!isset($matches[1])) {
throw new Exception(self::$errors['could_not_fetch_page']);
}
return $matches[1];
}
}
77 changes: 77 additions & 0 deletions scripts/fetchEdgeVersions/Wikipedia.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

class Wikipedia
{
const URL = 'https://en.wikipedia.org/w/api.php?action=query&titles=Microsoft_Edge&prop=revisions&rvprop=content&rvsection=4&format=xml';

private static $errors = array(
'fetch_error' => 'Unable to fetch content',
'parse_error' => 'Unable to parse content',
);

public static function fetch()
{
$content = file_get_contents(self::URL);
if (!$content) {
throw new Exception(self::$errors['fetch_error']);
}
$content = explode('===Release history===', $content);
if (!isset($content[1])) {
throw new Exception(self::$errors['parse_error']);
}
$table = explode('|-', $content[1]);
if (!isset($table[1])) {
throw new Exception(self::$errors['parse_error']);
}
$table = array_slice($table, 1);
$versions = array_map(array('Wikipedia', 'extractVersion'), $table);
self::writeEdgeVersions($versions);
}

private static function extractVersion($content)
{
$lines = array_slice(array_filter(
explode(PHP_EOL, $content),
function ($val) {
return trim($val) && strpos($val, '|') === 0;
}
), 0, 2);

preg_match("/{[^}{]*Version[^}{]*\| ?([\d\.]+)}/", $lines[0], $edgeVersion);
preg_match("/\| *(\d*\.\d*)/", $lines[1], $edgeHtmlVersion);

if (!isset($edgeVersion[1])) {
throw new Exception(self::$errors['parse_error']);
}
if (!isset($edgeHtmlVersion[1])) {
throw new Exception(self::$errors['parse_error']);
}

return array($edgeHtmlVersion[1], $edgeVersion[1]);
}

private static function writeEdgeVersions($versions)
{
$file = __DIR__ . '/../../src/edgeVersionMap.php';
$currentVersions = require $file;

foreach ($versions as $version) {
$currentVersions[$version[0]] = $version[1];
}
ksort($currentVersions);

$content = '';
foreach ($currentVersions as $edgeHtml => $edge) {
$content .= " '{$edgeHtml}' => '{$edge}'," . PHP_EOL;
}
$data = <<<PHP
<?php

return array(
%s
);

PHP;
file_put_contents($file, sprintf($data, trim($content)));
}
}
7 changes: 7 additions & 0 deletions scripts/fetchEdgeVersions/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

require_once __DIR__ . '/ChangeWindows.php';
require_once __DIR__ . '/Wikipedia.php';

Wikipedia::fetch();
ChangeWindows::fetchVersions();
29 changes: 29 additions & 0 deletions scripts/fetchEdgeVersions/windowsVersions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"15002": true,
"15007": true,
"15009": true,
"15014": true,
"15019": true,
"15023": true,
"15025": true,
"15026": true,
"15031": true,
"15034": true,
"15038": true,
"15039": true,
"15042": true,
"15043": true,
"15045": true,
"15046": true,
"15047": true,
"15048": true,
"15049": true,
"15051": true,
"15055": true,
"15058": true,
"15060": true,
"15061": true,
"15062": true,
"15063": true,
"16170": true
}
1 change: 1 addition & 0 deletions src/Browser.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Browser
const GSA = 'Google Search Appliance';
const YANDEX = 'Yandex';
const EDGE = 'Edge';
const EDGE_HTML = 'EdgeHTML';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could lead to use error, I'd prefer to still have Edge as the browser and the version be unknown if it is unknown.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I am working on engine detection also, so that fits.

const DRAGON = 'Dragon';
const NSPLAYER = 'Windows Media Player';
const UCBROWSER = 'UC Browser';
Expand Down
83 changes: 78 additions & 5 deletions src/BrowserDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,72 @@ class BrowserDetector implements DetectorInterface
'Mozilla', /* Mozilla is such an open standard that you must check it last */
);

//https://en.wikipedia.org/wiki/Microsoft_Edge
protected static $edgeHTML = [
"12.10049" => "0.10.10049",
"12.10051" => "0.11.10051",
"12.10052" => "0.11.10052",
"12.10061" => "0.11.10061",
"12.10074" => "0.11.10074",
"12.1008" => "0.11.10080",
"12.10122" => "13.10122",
"12.1013" => "15.1013",
"12.10136" => "16.10136",
"12.10149" => "19.10149",
"12.10158" => "20.10158",
"12.10159" => "20.10159",
"12.10162" => "20.10162",
"12.10166" => "20.10166",
"12.1024" => "20.1024",
"12.10512" => "20.10512",
"12.10514" => "20.10514",
"12.10525" => "20.10525",
"12.10532" => "20.10532",
"12.10536" => "20.10536",
"13.10547" => "21.10547",
"13.10549" => "21.10549",
"13.10565" => "23.10565",
"13.10572" => "25.10572",
"13.10576" => "25.10576",
"13.10581" => "25.10581",
"13.10586" => "25.10586",
"13.11082" => "25.11082",
"13.11099" => "27.11099",
"13.11102" => "28.11102",
"13.14251" => "28.14251",
"13.14257" => "28.14257",
"14.14267" => "31.14267",
"14.14271" => "31.14271",
"14.14279" => "31.14279",
"14.14283" => "31.14283",
"14.14291" => "34.14291",
"14.14295" => "34.14295",
"14.143" => "34.143",
"14.14316" => "37.14316",
"14.14322" => "37.14322",
"14.14327" => "37.14327",
"14.14328" => "37.14328",
"14.14332" => "37.14332",
"14.14342" => "38.14342",
"14.14352" => "38.14352",
"14.14393" => "38.14393",
"14.14901" => "39.14901",
"14.14905" => "39.14905",
"14.14915" => "39.14915",
"14.14926" => "39.14926",
"14.14931" => "39.14931",
"14.14936" => "39.14936",
"15.14942" => "39.14942",
"15.14946" => "39.14946",
"15.14951" => "39.14951",
"15.14955" => "39.14955",
"15.14959" => "39.14959",
"15.14965" => "39.14965",
"15.14971" => "39.14971",
"15.14977" => "39.14977",
"15.14986" => "39.14986"
];

/**
* Routine to determine the browser type.
*
Expand Down Expand Up @@ -471,11 +537,18 @@ public static function checkBrowserVivaldi()
public static function checkBrowserEdge()
{
if (stripos(self::$userAgentString, 'Edge') !== false) {
$version = explode('Edge/', self::$userAgentString);
if (isset($version[1])) {
self::$browser->setVersion((float)$version[1]);
preg_match('/Edge[\\/ \\(]([a-zA-Z\\d\\.]*)/i', self::$userAgentString, $matches);
if (sizeof($matches)>1) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check if the version is between the range and provide the closest version if it is.

Example:

"12.10049" => "0.10.10049",
"12.10051" => "0.11.10051",

If we detect version 12.10050, we should fallback to the latest available version which would be 0.10.10049. This way, while it may not be 100% accurate, it will provide a fallback to the versions missing in the table.

if (isset(self::$edgeHTML[$matches[1]])) {
self::$browser->setName(Browser::EDGE);
self::$browser->setVersion(self::$edgeHTML[$matches[1]]);
} else {
self::$browser->setName(Browser::EDGE_HTML);
self::$browser->setVersion($matches[1]);
}
} else {
self::$browser->setName(Browser::EDGE);
}
self::$browser->setName(Browser::EDGE);

return true;
}
Expand Down Expand Up @@ -960,7 +1033,7 @@ public static function checkBrowserYandex()

return false;
}

/**
* Determine if the browser is Comodo Dragon / Ice Dragon / Chromodo.
*
Expand Down
Loading