[ Index ]

PHP Cross Reference of Moodle 310

title

Body

[close]

/ -> GruntfileComponents.js (source)

   1  // This file is part of Moodle - http://moodle.org/
   2  //
   3  // Moodle is free software: you can redistribute it and/or modify
   4  // it under the terms of the GNU General Public License as published by
   5  // the Free Software Foundation, either version 3 of the License, or
   6  // (at your option) any later version.
   7  //
   8  // Moodle is distributed in the hope that it will be useful,
   9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11  // GNU General Public License for more details.
  12  //
  13  // You should have received a copy of the GNU General Public License
  14  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  15  
  16  /**
  17   * Helper functions for working with Moodle component names, directories, and sources.
  18   *
  19   * @copyright  2019 Andrew Nicols <andrew@nicols.co.uk>
  20   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21   */
  22  
  23  "use strict";
  24  /* eslint-env node */
  25  
  26  /** @var {Object} A list of subsystems in Moodle */
  27  const componentData = {};
  28  
  29  /**
  30   * Load details of all moodle modules.
  31   *
  32   * @returns {object}
  33   */
  34  const fetchComponentData = () => {
  35      const fs = require('fs');
  36      const path = require('path');
  37      const glob = require('glob');
  38      const gruntFilePath = process.cwd();
  39  
  40      if (!Object.entries(componentData).length) {
  41          componentData.subsystems = {};
  42          componentData.pathList = [];
  43  
  44          // Fetch the component definiitions from the distributed JSON file.
  45          const components = JSON.parse(fs.readFileSync(`$gruntFilePath}/lib/components.json`));
  46  
  47          // Build the list of moodle subsystems.
  48          componentData.subsystems.lib = 'core';
  49          componentData.pathList.push(process.cwd() + path.sep + 'lib');
  50          for (const [component, thisPath] of Object.entries(components.subsystems)) {
  51              if (thisPath) {
  52                  // Prefix "core_" to the front of the subsystems.
  53                  componentData.subsystems[thisPath] = `core_$component}`;
  54                  componentData.pathList.push(process.cwd() + path.sep + thisPath);
  55              }
  56          }
  57  
  58          // The list of components incldues the list of subsystems.
  59          componentData.components = componentData.subsystems;
  60  
  61          // Go through each of the plugintypes.
  62          Object.entries(components.plugintypes).forEach(([pluginType, pluginTypePath]) => {
  63              // We don't allow any code in this place..?
  64              glob.sync(`$pluginTypePath}/*/version.php`).forEach(versionPath => {
  65                  const componentPath = fs.realpathSync(path.dirname(versionPath));
  66                  const componentName = path.basename(componentPath);
  67                  const frankenstyleName = `${pluginType}_${componentName}`;
  68                  componentData.components[`${pluginTypePath}/${componentName}`] = frankenstyleName;
  69                  componentData.pathList.push(componentPath);
  70  
  71                  // Look for any subplugins.
  72                  const subPluginConfigurationFile = `${componentPath}/db/subplugins.json`;
  73                  if (fs.existsSync(subPluginConfigurationFile)) {
  74                      const subpluginList = JSON.parse(fs.readFileSync(fs.realpathSync(subPluginConfigurationFile)));
  75  
  76                      Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => {
  77                          glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => {
  78                              const componentPath = fs.realpathSync(path.dirname(versionPath));
  79                              const componentName = path.basename(componentPath);
  80                              const frankenstyleName = `$subpluginType}_$componentName}`;
  81  
  82                              componentData.components[`$subpluginTypePath}/$componentName}`] = frankenstyleName;
  83                              componentData.pathList.push(componentPath);
  84                          });
  85                      });
  86                  }
  87              });
  88          });
  89  
  90      }
  91  
  92      return componentData;
  93  };
  94  
  95  /**
  96   * Get the list of paths to build AMD sources.
  97   *
  98   * @returns {Array}
  99   */
 100  const getAmdSrcGlobList = () => {
 101      const globList = [];
 102      fetchComponentData().pathList.forEach(componentPath => {
 103          globList.push(`$componentPath}/amd/src/*.js`);
 104          globList.push(`${componentPath}/amd/src/**/*.js`);
 105      });
 106  
 107      return globList;
 108  };
 109  
 110  /**
 111   * Get the list of paths to build YUI sources.
 112   *
 113   * @param {String} relativeTo
 114   * @returns {Array}
 115   */
 116  const getYuiSrcGlobList = relativeTo => {
 117      const globList = [];
 118      fetchComponentData().pathList.forEach(componentPath => {
 119          const relativeComponentPath = componentPath.replace(relativeTo, '');
 120          globList.push(`$relativeComponentPath}/yui/src/**/*.js`);
 121      });
 122  
 123      return globList;
 124  };
 125  
 126  /**
 127   * Get the list of paths to thirdpartylibs.xml.
 128   *
 129   * @param {String} relativeTo
 130   * @returns {Array}
 131   */
 132  const getThirdPartyLibsList = relativeTo => {
 133      const fs = require('fs');
 134      const path = require('path');
 135  
 136      return fetchComponentData().pathList
 137          .map(componentPath => path.relative(relativeTo, componentPath) + '/thirdpartylibs.xml')
 138          .map(componentPath => componentPath.replace(/\\/g, '/'))
 139          .filter(path => fs.existsSync(path))
 140          .sort();
 141  };
 142  
 143  /**
 144   * Get the list of thirdparty library paths.
 145   *
 146   * @returns {array}
 147   */
 148  const getThirdPartyPaths = () => {
 149      const DOMParser = require('xmldom').DOMParser;
 150      const fs = require('fs');
 151      const path = require('path');
 152      const xpath = require('xpath');
 153  
 154      const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./'));
 155      const libs = ['node_modules/', 'vendor/'];
 156  
 157      const addLibToList = lib => {
 158          if (!lib.match('\\*') && fs.statSync(lib).isDirectory()) {
 159              // Ensure trailing slash on dirs.
 160              lib = lib.replace(/\/?$/, '/');
 161          }
 162  
 163          // Look for duplicate paths before adding to array.
 164          if (libs.indexOf(lib) === -1) {
 165              libs.push(lib);
 166          }
 167      };
 168  
 169      thirdpartyfiles.forEach(function(file) {
 170          const dirname = path.dirname(file);
 171  
 172          const xmlContent = fs.readFileSync(file, 'utf8');
 173          const doc = new DOMParser().parseFromString(xmlContent);
 174          const nodes = xpath.select("/libraries/library/location/text()", doc);
 175  
 176          nodes.forEach(function(node) {
 177              let lib = path.posix.join(dirname, node.toString());
 178              addLibToList(lib);
 179          });
 180      });
 181  
 182      return libs;
 183  
 184  };
 185  
 186  
 187  /**
 188   * Find the name of the component matching the specified path.
 189   *
 190   * @param {String} path
 191   * @returns {String|null} Name of matching component.
 192   */
 193  const getComponentFromPath = path => {
 194      const componentList = fetchComponentData().components;
 195  
 196      if (componentList.hasOwnProperty(path)) {
 197          return componentList[path];
 198      }
 199  
 200      return null;
 201  };
 202  
 203  /**
 204   * Check whether the supplied path, relative to the Gruntfile.js, is in a known component.
 205   *
 206   * @param {String} checkPath The path to check. This can be with either Windows, or Linux directory separators.
 207   * @returns {String|null}
 208   */
 209  const getOwningComponentDirectory = checkPath => {
 210      const path = require('path');
 211  
 212      // Fetch all components into a reverse sorted array.
 213      // This ensures that components which are within the directory of another component match first.
 214      const pathList = Object.keys(fetchComponentData().components).sort().reverse();
 215      for (const componentPath of pathList) {
 216          // If the componentPath is the directory being checked, it will be empty.
 217          // If the componentPath is a parent of the directory being checked, the relative directory will not start with ..
 218          if (!path.relative(componentPath, checkPath).startsWith('..')) {
 219              return componentPath;
 220          }
 221      }
 222  
 223      return null;
 224  };
 225  
 226  module.exports = {
 227      getAmdSrcGlobList,
 228      getComponentFromPath,
 229      getOwningComponentDirectory,
 230      getYuiSrcGlobList,
 231      getThirdPartyLibsList,
 232      getThirdPartyPaths,
 233  };


Generated: Wed Jan 22 11:59:49 2025 Cross-referenced by PHPXref 0.7.1