diff --git a/.travis.yml b/.travis.yml index 2d7f96a8b..4e41b34b3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ sudo: required -dist: xenial +dist: bionic group: edge language: node_js @@ -19,8 +19,8 @@ before_script: - gulp script: - - npm run build + - npm run build --bailOnLintError true --typeCheckOnLint true after_success: - - chmod +x scripts/aot.sh - - scripts/aot.sh + - scripts/ci.sh + \ No newline at end of file diff --git a/scripts/aot.sh b/scripts/aot.sh index 81c4d4ea8..4d3680e8a 100755 --- a/scripts/aot.sh +++ b/scripts/aot.sh @@ -1,76 +1,47 @@ #!/bin/bash +source "scripts/functions.sh" + +print_title "NPM packages list" # List first level of installed libraries so we can check the installed versions. npm list --depth=0 -# Compile AOT. -if [ $TRAVIS_BRANCH == 'integration' ] || [ $TRAVIS_BRANCH == 'master' ] || [ $TRAVIS_BRANCH == 'desktop' ] || [ $TRAVIS_BRANCH == 'security' ] || [ -z $TRAVIS_BRANCH ] ; then +if [ "$TRAVIS_BRANCH" == 'master' ] && [ ! -z $GIT_TOKEN ] && [ "$TRAVIS_REPO_SLUG" == 'moodlehq/moodleapp' ]; then + print_title "Update langpacks" cd scripts - ./build_lang.sh + ./update_lang.sh cd .. - if [ "$TRAVIS_BRANCH" == 'master' ] && [ ! -z $GIT_TOKEN ] ; then - git remote set-url origin https://$GIT_TOKEN@github.com/$TRAVIS_REPO_SLUG.git - git fetch -q origin - git add src/assets/lang - git add */en.json - git commit -m 'Update lang files [ci skip]' - git push origin HEAD:$TRAVIS_BRANCH - - version=`grep versionname src/config.json| cut -d: -f2|cut -d'"' -f2` - date=`date +%Y%m%d`'00' - - pushd ../moodle-local_moodlemobileapp - sed -ie "s/release[ ]*=[ ]*'[^']*';/release = '$version';/1" version.php - sed -ie "s/version[ ]*=[ ]*[0-9]*;/version = $date;/1" version.php - rm version.phpe - git remote set-url origin https://$GIT_TOKEN@github.com/moodlehq/moodle-local_moodlemobileapp.git - git fetch -q origin - git add . - git commit -m "Update lang files from $version" - git push - popd - fi - - sed -ie $'s~throw new Error("No ResourceLoader.*~url = "templates/" + url;\\\nvar resolve;\\\nvar reject;\\\nvar promise = new Promise(function (res, rej) {\\\nresolve = res;\\\nreject = rej;\\\n});\\\nvar xhr = new XMLHttpRequest();\\\nxhr.open("GET", url, true);\\\nxhr.responseType = "text";\\\nxhr.onload = function () {\\\nvar response = xhr.response || xhr.responseText;\\\nvar status = xhr.status === 1223 ? 204 : xhr.status;\\\nif (status === 0) {\\\nstatus = response ? 200 : 0;\\\n}\\\nif (200 <= status \&\& status <= 300) {\\\nresolve(response);\\\n}\\\nelse {\\\nreject("Failed to load " + url);\\\n}\\\n};\\\nxhr.onerror = function () { reject("Failed to load " + url); };\\\nxhr.send();\\\nreturn promise;\\\n~g' node_modules/@angular/platform-browser-dynamic/esm5/platform-browser-dynamic.js - sed -ie "s/context\.isProd || hasArg('--minifyJs')/hasArg('--minifyJs')/g" node_modules/@ionic/app-scripts/dist/util/config.js - sed -ie "s/context\.isProd || hasArg('--optimizeJs')/hasArg('--optimizeJs')/g" node_modules/@ionic/app-scripts/dist/util/config.js - npm run ionic:build -- --prod + print_title "Update generated lang files" + git remote set-url origin https://$GIT_TOKEN@github.com/$TRAVIS_REPO_SLUG.git + git fetch -q origin + git add -A src/assets/lang + git add */en.json + git add src/config.json + git commit -m 'Update lang files [ci skip]' + git push origin HEAD:$TRAVIS_BRANCH fi -# Copy to PGB git (only on a configured travis build). -if [ ! -z $GIT_ORG ] && [ ! -z $GIT_TOKEN ] ; then - gitfolder=${PWD##*/} - git clone --depth 1 --no-single-branch https://github.com/$GIT_ORG/moodlemobile-phonegapbuild.git ../pgb - pushd ../pgb +print_title "AOT Compilation" +sed -ie $'s~throw new Error("No ResourceLoader.*~url = "templates/" + url;\\\nvar resolve;\\\nvar reject;\\\nvar promise = new Promise(function (res, rej) {\\\nresolve = res;\\\nreject = rej;\\\n});\\\nvar xhr = new XMLHttpRequest();\\\nxhr.open("GET", url, true);\\\nxhr.responseType = "text";\\\nxhr.onload = function () {\\\nvar response = xhr.response || xhr.responseText;\\\nvar status = xhr.status === 1223 ? 204 : xhr.status;\\\nif (status === 0) {\\\nstatus = response ? 200 : 0;\\\n}\\\nif (200 <= status \&\& status <= 300) {\\\nresolve(response);\\\n}\\\nelse {\\\nreject("Failed to load " + url);\\\n}\\\n};\\\nxhr.onerror = function () { reject("Failed to load " + url); };\\\nxhr.send();\\\nreturn promise;\\\n~g' node_modules/@angular/platform-browser-dynamic/esm5/platform-browser-dynamic.js +sed -ie "s/context\.isProd || hasArg('--minifyJs')/hasArg('--minifyJs')/g" node_modules/@ionic/app-scripts/dist/util/config.js +sed -ie "s/context\.isProd || hasArg('--optimizeJs')/hasArg('--optimizeJs')/g" node_modules/@ionic/app-scripts/dist/util/config.js +npm run ionic:build -- --prod - mkdir /tmp/travistemp - cp .travis.yml /tmp/travistemp - mkdir /tmp/travistemp/scripts - cp scripts/* /tmp/travistemp/scripts - git checkout $TRAVIS_BRANCH - - rm -Rf assets build index.html templates www destkop lib - - if [ $TRAVIS_BRANCH == 'desktop' ] ; then - cp -Rf ../$gitfolder/desktop ./ - cp -Rf ../$gitfolder/package.json ./ - cp -Rf ../$gitfolder/www ./ - rm -Rf www/assets/countries www/assets/mimetypes - else - cp -Rf ../$gitfolder/www/* ./ - rm -Rf assets/countries assets/mimetypes +if [ $TRAVIS_BRANCH == 'integration' ] || [ $TRAVIS_BRANCH == 'master' ] || [ $TRAVIS_BRANCH == 'desktop' ] ; then + if [ ! -z $GIT_ORG_PRIVATE ] && [ ! -z $GIT_TOKEN ] ; then + if [ "$TRAVIS_REPO_SLUG" == 'moodlehq/moodleapp' ]; then + print_title "Mirror repository" + git remote add mirror https://$GIT_TOKEN@github.com/$GIT_ORG_PRIVATE/moodleapp.git + git fetch -q mirror + git push -f mirror HEAD:$TRAVIS_BRANCH + git push mirror --tags + else + print_title "Run scripts" + git clone --depth 1 https://$GIT_TOKEN@github.com/$GIT_ORG_PRIVATE/apps-scripts.git ../scripts + cp ../scripts/build.sh scripts/ + ./scripts/build.sh + fi fi - - cp /tmp/travistemp/.travis.yml .travis.yml - mkdir scripts - cp /tmp/travistemp/scripts/* scripts - - - git add . - git commit -m "Travis build: $TRAVIS_BUILD_NUMBER" - git push https://$GIT_TOKEN@github.com/$GIT_ORG/moodlemobile-phonegapbuild.git - popd fi - diff --git a/scripts/ci.sh b/scripts/ci.sh new file mode 100755 index 000000000..a8aaec045 --- /dev/null +++ b/scripts/ci.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ $TRAVIS_EVENT_TYPE == 'cron' ] ; then + # Tests scripts. + echo 'CRON NOT IMPLEMENTED YET' +else + ./scripts/aot.sh +fi diff --git a/scripts/get_ws_changes.php b/scripts/get_ws_changes.php deleted file mode 100644 index d5b91f9f0..000000000 --- a/scripts/get_ws_changes.php +++ /dev/null @@ -1,99 +0,0 @@ -. - -/** - * Script for converting a PHP WS structure to a TS type. - * - * The first parameter (required) is the path to the Moodle installation to use. - * The second parameter (required) is the name to the WS to convert. - * The third parameter (optional) is a number: 1 to convert the params structure, - * 0 to convert the returns structure. Defaults to 0. - */ - -if (!isset($argv[1])) { - echo "ERROR: Please pass the path to the folder containing the Moodle installations as the first parameter.\n"; - die(); -} - - -if (!isset($argv[2])) { - echo "ERROR: Please pass the WS name as the second parameter.\n"; - die(); -} - -define('CLI_SCRIPT', true); -require_once('ws_to_ts_functions.php'); - -$versions = array('master', '37', '36', '35', '34', '33', '32', '31'); - -$moodlespath = $argv[1]; -$wsname = $argv[2]; -$useparams = !!(isset($argv[3]) && $argv[3]); -$pathseparator = '/'; - -// Get the path to the script. -$index = strrpos(__FILE__, $pathseparator); -if ($index === false) { - $pathseparator = '\\'; - $index = strrpos(__FILE__, $pathseparator); -} -$scriptfolder = substr(__FILE__, 0, $index); -$scriptpath = concatenate_paths($scriptfolder, 'get_ws_structure.php', $pathseparator); - -$previousstructure = null; -$previousversion = null; -$libsloaded = false; - -foreach ($versions as $version) { - $moodlepath = concatenate_paths($moodlespath, 'stable_' . $version, $pathseparator); - - if (!$libsloaded) { - $libsloaded = true; - - require($moodlepath . '/config.php'); - require($CFG->dirroot . '/webservice/lib.php'); - } - - // Get the structure in this Moodle version. - $structure = shell_exec("php $scriptpath $moodlepath $wsname " . ($useparams ? 'true' : '')); - - if (strpos($structure, 'ERROR:') === 0) { - echo "WS not found in version $version. Stop.\n"; - break; - } - - $structure = unserialize($structure); - - if ($previousstructure != null) { - echo "*** Check changes from version $version to $previousversion ***\n"; - - $messages = detect_ws_changes($previousstructure, $structure); - - if (count($messages) > 0) { - $haschanged = true; - - foreach($messages as $message) { - echo "$message\n"; - } - } else { - echo "No changes found.\n"; - } - echo "\n"; - } - - $previousstructure = $structure; - $previousversion = $version; -} diff --git a/scripts/get_ws_structure.php b/scripts/get_ws_structure.php deleted file mode 100644 index bfa975ee9..000000000 --- a/scripts/get_ws_structure.php +++ /dev/null @@ -1,55 +0,0 @@ -. - -/** - * Script for getting the PHP structure of a WS returns or params. - * - * The first parameter (required) is the path to the Moodle installation to use. - * The second parameter (required) is the name to the WS to convert. - * The third parameter (optional) is a number: 1 to convert the params structure, - * 0 to convert the returns structure. Defaults to 0. - */ - -if (!isset($argv[1])) { - echo "ERROR: Please pass the Moodle path as the first parameter.\n"; - die(); -} - - -if (!isset($argv[2])) { - echo "ERROR: Please pass the WS name as the second parameter.\n"; - die(); -} - -$moodlepath = $argv[1]; -$wsname = $argv[2]; -$useparams = !!(isset($argv[3]) && $argv[3]); - -define('CLI_SCRIPT', true); - -require($moodlepath . '/config.php'); -require($CFG->dirroot . '/webservice/lib.php'); -require_once('ws_to_ts_functions.php'); - -$structure = get_ws_structure($wsname, $useparams); - -if ($structure === false) { - echo "ERROR: The WS wasn't found in this Moodle installation.\n"; - die(); -} - -remove_default_closures($structure); -echo serialize($structure); diff --git a/scripts/get_ws_ts.php b/scripts/get_ws_ts.php deleted file mode 100644 index 900a153b8..000000000 --- a/scripts/get_ws_ts.php +++ /dev/null @@ -1,62 +0,0 @@ -. - -/** - * Script for converting a PHP WS structure to a TS type. - * - * The first parameter (required) is the path to the Moodle installation to use. - * The second parameter (required) is the name to the WS to convert. - * The third parameter (optional) is the name to put to the TS type. Defaults to "TypeName". - * The fourth parameter (optional) is a number: 1 to convert the params structure, - * 0 to convert the returns structure. Defaults to 0. - */ - -if (!isset($argv[1])) { - echo "ERROR: Please pass the Moodle path as the first parameter.\n"; - die(); -} - - -if (!isset($argv[2])) { - echo "ERROR: Please pass the WS name as the second parameter.\n"; - die(); -} - -$moodlepath = $argv[1]; -$wsname = $argv[2]; -$typename = isset($argv[3]) ? $argv[3] : 'TypeName'; -$useparams = !!(isset($argv[4]) && $argv[4]); - -define('CLI_SCRIPT', true); - -require($moodlepath . '/config.php'); -require($CFG->dirroot . '/webservice/lib.php'); -require_once('ws_to_ts_functions.php'); - -$structure = get_ws_structure($wsname, $useparams); - -if ($structure === false) { - echo "ERROR: The WS wasn't found in this Moodle installation.\n"; - die(); -} - -if ($useparams) { - $description = "Params of WS $wsname."; -} else { - $description = "Result of WS $wsname."; -} - -echo get_ts_doc(null, $description, '') . "export type $typename = " . convert_to_ts(null, $structure, $useparams) . ";\n"; diff --git a/scripts/remove-jsdocs-types.js b/scripts/remove-jsdocs-types.js deleted file mode 100644 index 0392c4d1c..000000000 --- a/scripts/remove-jsdocs-types.js +++ /dev/null @@ -1,71 +0,0 @@ -const fs = require('fs') -const path = require('path') - -const srcPath = path.join(__dirname, '..', 'src') - -function findFiles(dirPath) { - const result = [] - const entries = fs.readdirSync(dirPath, {withFileTypes: true}) - - entries.forEach((entry) => { - const entryPath = path.join(dirPath, entry.name) - if (entry.isFile() && entry.name.endsWith('.ts')) { - result.push(entryPath) - } else if (entry.isDirectory()) { - result.push(...findFiles(entryPath)) - } - }) - - return result -} - -findFiles(srcPath).forEach((file) => { - let src = fs.readFileSync(file, 'utf-8') - - // Fix wrong use of @type instead of @return. - src = src.replace(/(\n +\* \@param [^\n]*\n +\* )\@type /g, (match, p1) => p1 + '@return ') - - // Remove square brackets and default values from @param lines. - src = src.replace(/(\n +\* @param +\{[^\n]+\} +)\[(\w+)[^\]\n]*\]/g, (match, p1, p2) => p1 + p2) - - // Remove types from @param and @return lines. - src = src.replace(/(\n +\* \@(?:param|returns?) *)([a-zA-Z0-9_]+ *)?(\{[^\n]*)/g, (match, p1, p2, p3) => { - p2 = p2 || '' - let brackets = 1; - let end = 0; - for (let i = 1; brackets > 0 && i < p3.length; i++) { - if (p3[i] == '{') { - brackets++ - } else if (p3[i] == '}') { - brackets-- - end = i + 1 - } - } - p1 = p1.trimEnd().replace('@returns', '@return') - p2 = p2.trim() - p3 = p3.slice(end).trim().replace(/^([a-zA-Z0-9_]+) +/, '$1 ') - if (!p2 && !p3) return '' - return p1 + ' ' + p2 + (p2 && p3 ? ' ' + p3 : p3) - }) - - // Remove @type lines. - src = src.replace(/\n +\* \@type .*\n/g, '\n') - - // Remove consecutive empty doc lines. - src = src.replace(/\n *\* *(\n *\*\/? *\n)/g, (match, p1) => p1) - - // Remove empty docs. - src = src.replace(/\n *\/\*\*[ \n\*]+\*\/ *\n/g, '\n') - - // Fix indentation. - src = src.replace(/(\n +\* +(?:@param \w+|@return) )([^\n]*)((?:\n +\* +[^@\n][^\n]+)+)/g, (match, p1, p2, p3) => { - const indent = p1.length - p3 = p3.replace(/(\n +\*)( +)([^\n]+)/g, (match, p1, p2, p3) => { - p2 = new Array(Math.max(0, indent - p1.length + 1)).join(' ') - return p1 + p2 + p3 - }) - return p1 + p2 + p3 - }) - - fs.writeFileSync(file, src) -}) diff --git a/scripts/build_lang.sh b/scripts/update_lang.sh similarity index 100% rename from scripts/build_lang.sh rename to scripts/update_lang.sh diff --git a/scripts/ws_to_ts_functions.php b/scripts/ws_to_ts_functions.php deleted file mode 100644 index ca05d2082..000000000 --- a/scripts/ws_to_ts_functions.php +++ /dev/null @@ -1,244 +0,0 @@ -. - -/** - * Helper functions for converting a Moodle WS structure to a TS type. - */ - -/** - * Get the structure of a WS params or returns. - */ -function get_ws_structure($wsname, $useparams) { - global $DB; - - // get all the function descriptions - $functions = $DB->get_records('external_functions', array(), 'name'); - $functiondescs = array(); - foreach ($functions as $function) { - $functiondescs[$function->name] = external_api::external_function_info($function); - } - - if (!isset($functiondescs[$wsname])) { - return false; - } else if ($useparams) { - return $functiondescs[$wsname]->parameters_desc; - } else { - return $functiondescs[$wsname]->returns_desc; - } -} - -/** - * Fix a comment: make sure first letter is uppercase and add a dot at the end if needed. - */ -function fix_comment($desc) { - $desc = trim($desc); - $desc = ucfirst($desc); - - if (substr($desc, -1) !== '.') { - $desc .= '.'; - } - - return $desc; -} - -/** - * Get an inline comment based on a certain text. - */ -function get_inline_comment($desc) { - if (empty($desc)) { - return ''; - } - - return ' // ' . fix_comment($desc); -} - -/** - * Add the TS documentation of a certain element. - */ -function get_ts_doc($type, $desc, $indentation) { - if (empty($desc)) { - // If no key, it's probably in an array. We only document object properties. - return ''; - } - - return $indentation . "/**\n" . - $indentation . " * " . fix_comment($desc) . "\n" . - (!empty($type) ? ($indentation . " * @type {" . $type . "}\n") : '') . - $indentation . " */\n"; -} - -/** - * Specify a certain type, with or without a key. - */ -function convert_key_type($key, $type, $required, $indentation) { - if ($key) { - // It has a key, it's inside an object. - return $indentation . "$key" . ($required == VALUE_OPTIONAL ? '?' : '') . ": $type"; - } else { - // No key, it's probably in an array. Just include the type. - return $type; - } -} - -/** - * Convert a certain element into a TS structure. - */ -function convert_to_ts($key, $value, $boolisnumber = false, $indentation = '', $arraydesc = '') { - if ($value instanceof external_value || $value instanceof external_warnings || $value instanceof external_files) { - // It's a basic field or a pre-defined type like warnings. - $type = 'string'; - - if ($value instanceof external_warnings) { - $type = 'CoreWSExternalWarning[]'; - } else if ($value instanceof external_files) { - $type = 'CoreWSExternalFile[]'; - } else if ($value->type == PARAM_BOOL && !$boolisnumber) { - $type = 'boolean'; - } else if (($value->type == PARAM_BOOL && $boolisnumber) || $value->type == PARAM_INT || $value->type == PARAM_FLOAT || - $value->type == PARAM_LOCALISEDFLOAT || $value->type == PARAM_PERMISSION || $value->type == PARAM_INTEGER || - $value->type == PARAM_NUMBER) { - $type = 'number'; - } - - $result = convert_key_type($key, $type, $value->required, $indentation); - - return $result; - - } else if ($value instanceof external_single_structure) { - // It's an object. - $result = convert_key_type($key, '{', $value->required, $indentation); - - if ($arraydesc) { - // It's an array of objects. Print the array description now. - $result .= get_inline_comment($arraydesc); - } - - $result .= "\n"; - - foreach ($value->keys as $key => $value) { - $result .= convert_to_ts($key, $value, $boolisnumber, $indentation . ' ') . ';'; - - if (!$value instanceof external_multiple_structure || !$value->content instanceof external_single_structure) { - // Add inline comments after the field, except for arrays of objects where it's added at the start. - $result .= get_inline_comment($value->desc); - } - - $result .= "\n"; - } - - $result .= "$indentation}"; - - return $result; - - } else if ($value instanceof external_multiple_structure) { - // It's an array. - $result = convert_key_type($key, '', $value->required, $indentation); - - $result .= convert_to_ts(null, $value->content, $boolisnumber, $indentation, $value->desc); - - $result .= "[]"; - - return $result; - } else { - echo "WARNING: Unknown structure: $key " . get_class($value) . " \n"; - - return ""; - } -} - -/** - * Concatenate two paths. - */ -function concatenate_paths($left, $right, $separator = '/') { - if (!is_string($left) || $left == '') { - return $right; - } else if (!is_string($right) || $right == '') { - return $left; - } - - $lastCharLeft = substr($left, -1); - $firstCharRight = $right[0]; - - if ($lastCharLeft === $separator && $firstCharRight === $separator) { - return $left . substr($right, 1); - } else if ($lastCharLeft !== $separator && $firstCharRight !== '/') { - return $left . '/' . $right; - } else { - return $left . $right; - } -} - -/** - * Detect changes between 2 WS structures. We only detect fields that have been added or modified, not removed fields. - */ -function detect_ws_changes($new, $old, $key = '', $path = '') { - $messages = []; - - if (gettype($new) != gettype($old)) { - // The type has changed. - $messages[] = "Property '$key' has changed type, from '" . gettype($old) . "' to '" . gettype($new) . - ($path != '' ? "' inside $path." : "'."); - - } else if ($new instanceof external_value && $new->type != $old->type) { - // The type has changed. - $messages[] = "Property '$key' has changed type, from '" . $old->type . "' to '" . $new->type . - ($path != '' ? "' inside $path." : "'."); - - } else if ($new instanceof external_warnings || $new instanceof external_files) { - // Ignore these types. - - } else if ($new instanceof external_single_structure) { - // Check each subproperty. - $newpath = ($path != '' ? "$path." : '') . $key; - - foreach ($new->keys as $subkey => $value) { - if (!isset($old->keys[$subkey])) { - // New property. - $messages[] = "New property '$subkey' found" . ($newpath != '' ? " inside '$newpath'." : '.'); - } else { - $messages = array_merge($messages, detect_ws_changes($value, $old->keys[$subkey], $subkey, $newpath)); - } - } - } else if ($new instanceof external_multiple_structure) { - // Recursive call with the content. - $messages = array_merge($messages, detect_ws_changes($new->content, $old->content, $key, $path)); - } - - return $messages; -} - -/** - * Remove all closures (anonymous functions) in the default values so the object can be serialized. - */ -function remove_default_closures($value) { - if ($value instanceof external_warnings || $value instanceof external_files) { - // Ignore these types. - - } else if ($value instanceof external_value) { - if ($value->default instanceof Closure) { - $value->default = null; - } - - } else if ($value instanceof external_single_structure) { - - foreach ($value->keys as $key => $subvalue) { - remove_default_closures($subvalue); - } - - } else if ($value instanceof external_multiple_structure) { - remove_default_closures($value->content); - } -} diff --git a/src/providers/utils/url.ts b/src/providers/utils/url.ts index af89f56c3..ec233b1c0 100644 --- a/src/providers/utils/url.ts +++ b/src/providers/utils/url.ts @@ -183,7 +183,7 @@ export class CoreUrlUtilsProvider { if (!this.isPluginFileUrl(url) || url.indexOf(this.textUtils.addEndingSlash(siteUrl)) !== 0) { return url; } - + if (canUseTokenPluginFile) { // Use tokenpluginfile.php. url = url.replace(/(\/webservice)?\/pluginfile\.php/, '/tokenpluginfile.php/' + accessKey);