<commit_before>(function (exports) {

  const NODE_JS = 1;
  const JS_SHELL = 2;
  const BROWSER = 3;

  var mode;
  if (typeof process !== "undefined") {
    mode = NODE_JS;
  } else if (typeof snarf !== "undefined") {
    mode = JS_SHELL;
  } else {
    mode = BROWSER;
  }

  var util, esprima, escodegen, estransform, compiler;
  var argv;

  if (mode === NODE_JS) {
    util = require("./util.js");
    esprima = require("./esprima.js");
    escodegen = require("./escodegen.js");
    estransform = require("./estransform.js");
    compiler = require("./compiler.js");

    snarf = require('fs').readFileSync;
    argv = process.argv.slice(2);
    print = console.log;
    quit = process.exit;
  } else if (mode === JS_SHELL) {
    load("./util.js");
    load("./esprima.js");
    load("./escodegen.js");
    load("./estransform.js");
    load("./compiler.js");

    argv = this.arguments;
  }

  if (mode !== NODE_JS) {
    util = this.util;
    esprima = this.esprima;
    escodegen = this.escodegen;
    estransform = this.estransform;
    compiler = this.compiler;
  }

  const assert = util.assert;
  const lang = estransform.lang;
  const allFields = estransform.allFields;

  function pretty(node, indent) {
    if (typeof indent === "undefined") {
      indent = "";
    }

    var s = "";

    if (node instanceof Array) {
      for (var i = 0, j = node.length; i < j; i++) {
        s += pretty(node[i], indent);
      }
      return s;
    }

    s += indent + node.type;

    var spec = lang[node.type];
    if (!spec) {
      s += " ???\n";
      return;
    }

    var fields = allFields(spec);
    var children = [];
    var values = [];
    // We do loc manually.
    fields.pop();
    for (var i = 0, j = fields.length; i < j; i++) {
      var fname = fields[i];
      if (fname.charAt(0) === "@") {
        fname = fname.substr(1);
        if (node[fname]) {
          children.push(pretty(node[fname], indent + "  "));
        }
      } else {
        if (typeof node[fname] !== "undefined") {
          values.push(node[fname]);
        }
      }
    }

    if (values.length) {
      s += " '" + values.join("' '") + "'";
    }

    var loc = node.loc;
    if (loc) {
      s += (" (" + loc.start.line + ":" + loc.start.column + "-" +
            loc.end.line + ":" + loc.end.column + ")");
    }

    s += "\n" + children.join("");

    return s;
  }

  function cli() {
    var optparser = new util.OptParser([
      ["E", "only-parse",   false, "Only parse"],
      ["A", "emit-ast",     false, "Do not generate JS, emit AST"],
      ["P", "pretty-print", false, "Pretty-print AST instead of emitting JSON (with -A)"],
      ["b", "bare",         false, "Do not wrap in a module"],
      ["l", "load-instead", false, "Emit load('memory') instead of require('memory')"],
      ["W", "warn",         true,  "Print warnings (enabled by default)"],
      ["Wconversion", null, false, "Print intra-integer and pointer conversion warnings"],
      ["0", "simple-log",   false, "Log simple messages. No colors and snippets."],
      ["t", "trace",        false, "Trace compiler execution"],
      ["h", "help",         false, "Print this message"]
    ]);

    var p = optparser.parse(argv);
    if (!p) {
      quit();
    }

    var options = p.options;
    var files = p.rest;

    if (!files.length || options.help) {
      print("ljc: [option(s)] file");
      print(optparser.usage());
      quit();
    }

    var filename = files[0];
    var path = filename.split("/");
    var basename = path.pop();
    var dir = path.join("/");
    basename = basename.substr(0, basename.lastIndexOf(".")) || basename;

    var source = snarf(filename);
    var code = compile(basename, filename, source, options);

    if (options["pretty-print"]) {
      print(pretty(code));
    } else {
      // SpiderMonkey has no way to write to a file, but if we're on node we can
      // emit .js.
      if (mode === NODE_JS) {
        var outname = (dir ? dir + "/" : "") + basename;
        if (options["emit-ast"]) {
          require('fs').writeFileSync(outname + ".json", JSON.stringify(code, null, 2));
        } else {
          // Escodegen doesn't emit a final newline for some reason, so add one.
          require('fs').writeFileSync(outname + ".js", code + "\n");
        }
      } else {
        print(code);
      }
    }
  }

  function compile(name, logName, source, options) {
    // -W anything infers -W.
    for (var p in options) {
      if (p.charAt(0) === "W") {
        options.warn = true;
        break;
      }
    }

    var logger = new util.Logger("ljc", logName, source, options);
    var code;

    try {
      var node = esprima.parse(source, { loc: true, comment: true, range: true, tokens: true });

      node = escodegen.attachComments(node, node.comments, node.tokens);

      if (options["only-parse"]) {
        code = node;
      } else {
        node = compiler.compile(node, name, logger, options);
        if (options["emit-ast"]) {
          code = node;
        } else {
          code = escodegen.generate(node, { base: "", indent: "  ", comment: true });
        }
      }
    } catch (e) {
      if (mode === BROWSER) {
        throw e;
      }

      if (e.index) {
        // Esprima error, make a loc out of it.
        var lc = { line: e.lineNumber, column: e.column - 1 };
        e.loc = { start: lc, end: lc };
        logger.error(e.message, { start: lc, end: lc });
        logger.flush();
        quit();
      }

      if (e.logged && mode !== BROWSER) {
        // Compiler error that has already been logged, so just flush and
        // quit.
        logger.flush();
        quit();
      }

      throw e;
    }

    logger.flush();
    return code;
  }

  exports.cli = cli;
  exports.compile = compile;

  if (mode === JS_SHELL) {
    cli();
  }

}).call(this, typeof exports === "undefined" ? (LJC = {}) : exports);
<commit_msg>Bug fix: Should not overwrite source file with -E (only-parse)<commit_after>(function (exports) {

  const NODE_JS = 1;
  const JS_SHELL = 2;
  const BROWSER = 3;

  var mode;
  if (typeof process !== "undefined") {
    mode = NODE_JS;
  } else if (typeof snarf !== "undefined") {
    mode = JS_SHELL;
  } else {
    mode = BROWSER;
  }

  var util, esprima, escodegen, estransform, compiler;
  var argv;

  if (mode === NODE_JS) {
    util = require("./util.js");
    esprima = require("./esprima.js");
    escodegen = require("./escodegen.js");
    estransform = require("./estransform.js");
    compiler = require("./compiler.js");

    snarf = require('fs').readFileSync;
    argv = process.argv.slice(2);
    print = console.log;
    quit = process.exit;
  } else if (mode === JS_SHELL) {
    load("./util.js");
    load("./esprima.js");
    load("./escodegen.js");
    load("./estransform.js");
    load("./compiler.js");

    argv = this.arguments;
  }

  if (mode !== NODE_JS) {
    util = this.util;
    esprima = this.esprima;
    escodegen = this.escodegen;
    estransform = this.estransform;
    compiler = this.compiler;
  }

  const assert = util.assert;
  const lang = estransform.lang;
  const allFields = estransform.allFields;

  function pretty(node, indent) {
    if (typeof indent === "undefined") {
      indent = "";
    }

    var s = "";

    if (node instanceof Array) {
      for (var i = 0, j = node.length; i < j; i++) {
        s += pretty(node[i], indent);
      }
      return s;
    }

    s += indent + node.type;

    var spec = lang[node.type];
    if (!spec) {
      s += " ???\n";
      return;
    }

    var fields = allFields(spec);
    var children = [];
    var values = [];
    // We do loc manually.
    fields.pop();
    for (var i = 0, j = fields.length; i < j; i++) {
      var fname = fields[i];
      if (fname.charAt(0) === "@") {
        fname = fname.substr(1);
        if (node[fname]) {
          children.push(pretty(node[fname], indent + "  "));
        }
      } else {
        if (typeof node[fname] !== "undefined") {
          values.push(node[fname]);
        }
      }
    }

    if (values.length) {
      s += " '" + values.join("' '") + "'";
    }

    var loc = node.loc;
    if (loc) {
      s += (" (" + loc.start.line + ":" + loc.start.column + "-" +
            loc.end.line + ":" + loc.end.column + ")");
    }

    s += "\n" + children.join("");

    return s;
  }

  function cli() {
    var optparser = new util.OptParser([
      ["E", "only-parse",   false, "Only parse"],
      ["A", "emit-ast",     false, "Do not generate JS, emit AST"],
      ["P", "pretty-print", false, "Pretty-print AST instead of emitting JSON (with -A)"],
      ["b", "bare",         false, "Do not wrap in a module"],
      ["l", "load-instead", false, "Emit load('memory') instead of require('memory')"],
      ["W", "warn",         true,  "Print warnings (enabled by default)"],
      ["Wconversion", null, false, "Print intra-integer and pointer conversion warnings"],
      ["0", "simple-log",   false, "Log simple messages. No colors and snippets."],
      ["t", "trace",        false, "Trace compiler execution"],
      ["h", "help",         false, "Print this message"]
    ]);

    var p = optparser.parse(argv);
    if (!p) {
      quit();
    }

    var options = p.options;
    var files = p.rest;

    if (!files.length || options.help) {
      print("ljc: [option(s)] file");
      print(optparser.usage());
      quit();
    }

    var filename = files[0];
    var path = filename.split("/");
    var basename = path.pop();
    var dir = path.join("/");
    basename = basename.substr(0, basename.lastIndexOf(".")) || basename;

    var source = snarf(filename);
    var code = compile(basename, filename, source, options);

    if (options["pretty-print"]) {
      print(pretty(code));
    } else {
      // SpiderMonkey has no way to write to a file, but if we're on node we can
      // emit .js.
      if (mode === NODE_JS && !options["only-parse"]) {
        var outname = (dir ? dir + "/" : "") + basename;
        if (options["emit-ast"]) {
          require('fs').writeFileSync(outname + ".json", JSON.stringify(code, null, 2));
        } else {
          // Escodegen doesn't emit a final newline for some reason, so add one.
          require('fs').writeFileSync(outname + ".js", code + "\n");
        }
      } else {
        print(code);
      }
    }
  }

  function compile(name, logName, source, options) {
    // -W anything infers -W.
    for (var p in options) {
      if (p.charAt(0) === "W") {
        options.warn = true;
        break;
      }
    }

    var logger = new util.Logger("ljc", logName, source, options);
    var code;

    try {
      var node = esprima.parse(source, { loc: true, comment: true, range: true, tokens: true });

      node = escodegen.attachComments(node, node.comments, node.tokens);

      if (options["only-parse"]) {
        code = node;
      } else {
        node = compiler.compile(node, name, logger, options);
        if (options["emit-ast"]) {
          code = node;
        } else {
          code = escodegen.generate(node, { base: "", indent: "  ", comment: true });
        }
      }
    } catch (e) {
      if (mode === BROWSER) {
        throw e;
      }

      if (e.index) {
        // Esprima error, make a loc out of it.
        var lc = { line: e.lineNumber, column: e.column - 1 };
        e.loc = { start: lc, end: lc };
        logger.error(e.message, { start: lc, end: lc });
        logger.flush();
        quit();
      }

      if (e.logged && mode !== BROWSER) {
        // Compiler error that has already been logged, so just flush and
        // quit.
        logger.flush();
        quit();
      }

      throw e;
    }

    logger.flush();
    return code;
  }

  exports.cli = cli;
  exports.compile = compile;

  if (mode === JS_SHELL) {
    cli();
  }

}).call(this, typeof exports === "undefined" ? (LJC = {}) : exports);
<|endoftext|>


<commit_before>class Webcam extends React.Component {
  static propTypes = {
    audio: React.PropTypes.bool,
    width: React.PropTypes.number,
    height: React.PropTypes.number,
    captureFormat: React.PropTypes.oneOf([
      "image/png",
      "image/jpeg",
      "image/webp"
    ])
  };

  static defaultProps = {
    audio: true,
    width: 640,
    height: 480,
    captureFormat: "image/png"
  };

  static _mediaStream = null;
  static _captureCanvas = null;

  //---------------------------------------------------------------------------
  // Initialization
  //---------------------------------------------------------------------------

  constructor(props) {
    super(props);

    this.state = {
      hasUserMedia: false,
      userMediaRequested: false
    };
  }

  //---------------------------------------------------------------------------
  // Lifecycle methods
  //---------------------------------------------------------------------------

  componentDidMount() {
    if (!this._hasGetUserMedia()) {
      return false;
    }

    const { hasUserMedia, userMediaRequested } = this.state;
    if (!hasUserMedia && !userMediaRequested) {
      this._requestUserMedia();
    }
  }

  componentWillUnmount() {
    this._mediaStream.getTracks().forEach((track) => track.stop());
  }

  //---------------------------------------------------------------------------
  // External methods
  //---------------------------------------------------------------------------

  _hasGetUserMedia() {
    return !!(
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia ||
      navigator.msGetUserMedia
    );
  }

  _requestUserMedia() {
    navigator.getUserMedia = (
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia ||
      navigator.msGetUserMedia
    );

    let constraints = {
      video: true,
      audio: this.props.audio
    }

    navigator.getUserMedia(
      constraints,
      (stream) => {
        const video = this.refs.video;

        if (window.URL) {
          video.src = window.URL.createObjectURL(stream);
        } else {
          video.src = stream;
        }

        this._mediaStream = stream;

        this.setState({
          hasUserMedia: true,
          userMediaRequested: true
        });
      },
      (error) => {
        console.log("An error occured while requesting user media");
        throw(error);
      }
    );

  }

  _getCanvas() {
    if (this._captureCanvas) {
      return this._captureCanvas;
    }

    this._captureCanvas = document.createElement("canvas");
    this._captureCanvas.width = this.props.width;
    this._captureCanvas.height = this.props.height;

    return this._captureCanvas;
  }

  //---------------------------------------------------------------------------
  // External methods
  //---------------------------------------------------------------------------

  captureScreenshot() {
    const { hasUserMedia, userMediaRequested } = this.state;
    const { width, height, captureFormat } = this.props;

    if (hasUserMedia && userMediaRequested) {
      const canvas = this._getCanvas();
      const ctx = canvas.getContext("2d");

      ctx.drawImage(this.refs.video, 0, 0, width, height);

      return canvas.toDataURL(captureFormat);
    }
  }

  //---------------------------------------------------------------------------
  // Render
  //---------------------------------------------------------------------------

  render() {
    const { width, height } = this.props;

    return (
      <video
        width={width}
        height={height}
        ref="video"
        autoPlay
      />
    )
  }

};

export default Webcam;
<commit_msg>Do not import React, only Component and PropTypes<commit_after>import { Component, PropTypes } from "react";

class Webcam extends Component {
  static propTypes = {
    audio: PropTypes.bool,
    width: PropTypes.number,
    height: PropTypes.number,
    captureFormat: PropTypes.oneOf([
      "image/png",
      "image/jpeg",
      "image/webp"
    ])
  };

  static defaultProps = {
    audio: true,
    width: 640,
    height: 480,
    captureFormat: "image/png"
  };

  static _mediaStream = null;
  static _captureCanvas = null;

  //---------------------------------------------------------------------------
  // Initialization
  //---------------------------------------------------------------------------

  constructor(props) {
    super(props);

    this.state = {
      hasUserMedia: false,
      userMediaRequested: false
    };
  }

  //---------------------------------------------------------------------------
  // Lifecycle methods
  //---------------------------------------------------------------------------

  componentDidMount() {
    if (!this._hasGetUserMedia()) {
      return false;
    }

    const { hasUserMedia, userMediaRequested } = this.state;
    if (!hasUserMedia && !userMediaRequested) {
      this._requestUserMedia();
    }
  }

  componentWillUnmount() {
    this._mediaStream.getTracks().forEach((track) => track.stop());
  }

  //---------------------------------------------------------------------------
  // External methods
  //---------------------------------------------------------------------------

  _hasGetUserMedia() {
    return !!(
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia ||
      navigator.msGetUserMedia
    );
  }

  _requestUserMedia() {
    navigator.getUserMedia = (
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia ||
      navigator.msGetUserMedia
    );

    let constraints = {
      video: true,
      audio: this.props.audio
    }

    navigator.getUserMedia(
      constraints,
      (stream) => {
        const video = this.refs.video;

        if (window.URL) {
          video.src = window.URL.createObjectURL(stream);
        } else {
          video.src = stream;
        }

        this._mediaStream = stream;

        this.setState({
          hasUserMedia: true,
          userMediaRequested: true
        });
      },
      (error) => {
        console.log("An error occured while requesting user media");
        throw(error);
      }
    );

  }

  _getCanvas() {
    if (this._captureCanvas) {
      return this._captureCanvas;
    }

    this._captureCanvas = document.createElement("canvas");
    this._captureCanvas.width = this.props.width;
    this._captureCanvas.height = this.props.height;

    return this._captureCanvas;
  }

  //---------------------------------------------------------------------------
  // External methods
  //---------------------------------------------------------------------------

  captureScreenshot() {
    const { hasUserMedia, userMediaRequested } = this.state;
    const { width, height, captureFormat } = this.props;

    if (hasUserMedia && userMediaRequested) {
      const canvas = this._getCanvas();
      const ctx = canvas.getContext("2d");

      ctx.drawImage(this.refs.video, 0, 0, width, height);

      return canvas.toDataURL(captureFormat);
    }
  }

  //---------------------------------------------------------------------------
  // Render
  //---------------------------------------------------------------------------

  render() {
    const { width, height } = this.props;

    return (
      <video
        width={width}
        height={height}
        ref="video"
        autoPlay
      />
    )
  }

};

export default Webcam;
<|endoftext|>


<commit_before>this.BlackBox = (function(EventEmitter, extendClass, hasOwnProperty, Queue, getUndefined){
  var errorListener = function(e){

    if (!hasOwnProperty(this, "_lastError"))
      this._lastError = e;
  };
  var init = function(pins){

    var wires = [], blocks = [];
    for (var name in pins){

      // TODO Finish this function
    }
  };
  function BlackBox(hash){

    EventEmitter.call(this);

    this._updating = false;
    this._internalWires = {};
    this._externalWires = {};
    this._errorListener = errorListener.bind(this);

    if (typeof hash !== "undefined"){

      // Add pins if supplied
      if (hasOwnProperty(hash, "pins"))
        init.call(this, hash.pins);

      // Add queue if supplied
      if (hasOwnProperty(hash, "queue"))
        this._updateQueue = hash.queue;
    }

    // Set defaults
    if (!hasOwnProperty(this, "_updateQueue"))
      this._updateQueue = new Queue();
  }
  extendClass(EventEmitter, BlackBox);
  var P = BlackBox.prototype;
  P.update = function(pin){

    // A connected wire value changed

    // Check updating flag
    if (this._updating){

      // Add update to queue and return
      this._updateQueue.push(pin);
      return;
    }
    else
      this._updating = true; // Set updating flag

    // Main loop
    while (true){

      // Defensive copy external wires
      // Internal wires should never change
      var internalWires = this._internalWires, externalWires = {};
      for (var name in internalWires){

        if (this._externalWires[name])
          externalWires[name] = this._externalWires[name];
      }

      // Get updated pin value
      var value;
      if(externalWires[pin])
        value = externalWires[pin].value();
      else
        value = getUndefined();

      // Fire update event
      this.fire("update", {pin: pin, value: value});

      // Clear last error, if any
      delete this._lastError;

      // Copy values from external wires to internal wires
      for (var name in internalWires){

        if (externalWires[name])
          internalWires[name].value(externalWires[name].value());
        else
          internalWires[name].value(getUndefined());
      }

      // Handle successful run
      if (!hasOwnProperty(this, "_lastError")){

        // Fire event
        this.fire("success");

        // Copy values from internal wires to external wires
        for (var name in internalWires){

          if (externalWires[name])
            externalWires[name].value(internalWires[name].value());
        }
      }
      else
        this.fire("error", this._lastError); // Fire event

      // Proces update queue
      if (this._updateQueue.isEmpty()){

        // Unset updating flag and return
        this._updating = false;
        return;
      }
      else
        pin = this._updateQueue.next(); // Get next updated pin from queue

      // Restart loop
    }
  };
  return BlackBox;
}(this.EventEmitter, this.extendClass, this.hasOwnProperty, this.Queue, this.getUndefined));

<commit_msg>BlackBox init() and duplicate()<commit_after>this.BlackBox = (function(EventEmitter, extendClass, hasOwnProperty, Queue, getUndefined, Map, Set){
  var errorListener = function(e){

    if (!hasOwnProperty(this, "_lastError"))
      this._lastError = e;
  };
  var init = (function(){

    var processWire, processBlock;

    processWire = function(wire, wireSet, blockSet){

      // Check if this wire has already been processed
      if (!wireSet.has(wire)){

        // Wire has not been processed
        // Add wire to wire set
        wireSet.add(wire);

        // Process all blocks connected to the wire
        var it = wire.connections();
        while (!it.peek().done)
          processBlock(it.next().value.block, wireSet, blockSet);
      }
    };

    processBlock = function(block, wireSet, blockSet){

      // Check if this block has already been processed
      if (!blockSet.has(block)){

        // Block has not been processed
        // Add block to block set
        blockSet.add(block);

        // Process all wires connected to the block
        var it = block.connections();
        while (!it.peek().done)
          processWire(it.next().value.wire, wireSet, blockSet);
      }
    };

    return function(pins){

      // Create wire set and block set
      // These collect all wires and blocks in the network
      var wireSet = new Set();
      var blockSet = new Set();

      // Process pins hash
      for (var pin in pins){

        // Add pin to internal wire hash
        this._internalWires[pin] = pins[pin].wire;

        // Process the wire and all connected blocks
        processWire(pins[pin].wire, wireSet, blockSet);
      }

      // All blocks are in the block set now
      // Attach "error" event listener to all blocks in the network
      var it = blockSet.values();
      while (!it.peek().done)
        it.next().value.on("error", this._errorListener);
    };
  }());
  function BlackBox(hash){

    EventEmitter.call(this);

    this._updating = false;
    this._internalWires = {};
    this._externalWires = {};
    this._errorListener = errorListener.bind(this);

    if (typeof hash !== "undefined"){

      // Add pins if supplied
      if (hasOwnProperty(hash, "pins"))
        init.call(this, hash.pins);

      // Add queue if supplied
      if (hasOwnProperty(hash, "queue"))
        this._updateQueue = hash.queue;
    }

    // Set defaults
    if (!hasOwnProperty(this, "_updateQueue"))
      this._updateQueue = new Queue();
  }
  extendClass(EventEmitter, BlackBox);
  var P = BlackBox.prototype;
  P.duplicate = (function(){

    var processWire, processBlock;

    processWire = function(wire, wireMap, blockMap){

      // Check if this wire has already been processed
      var duplicate = wireMap.get(wire);
      if (duplicate)
        return duplicate;

      // Wire has not been processed
      // Duplicate the wire
      duplicate = wire.duplicate();

      // Add duplicate wire to wire map
      wireMap.put(wire, duplicate);

      // Process all blocks connected to the wire
      var it = wire.connections();
      while (!it.peek().done)
        processBlock(it.next().value.block, wireMap, blockMap);

      // Return duplicate wire
      return duplicate;
    };

    processBlock = function(block, wireMap, blockMap){

      // Check if this block has already been processed
      var duplicate = blockMap.get(block);
      if (duplicate)
        return duplicate;

      // Block has not been processed
      // Duplicate the block
      duplicate = block.duplicate();

      // Add duplicate block to block map
      blockMap.put(block, duplicate);

      // Process all wires connected to the block
      var it = block.connections();
      while (!it.peek().done){

        // Process and get the duplicate wire
        var wire = processWire(it.peek().value.wire, wireMap, blockMap);

        // Connect the duplicate block to the duplicate wire
        duplicate.connect(it.next().value.pin, wire);
      }

      // Return duplicate block
      return duplicate;
    };

    return function(){

      // Create wire map and block map
      // These map wires and blocks in the original circuit to their duplicates
      var wireMap = new Map();
      var blockMap = new Map();

      // Construct pins hash for the new BlackBox
      var pins;
      for (var pin in this._internalWires)
        pins[pin] = processWire(this._internalWires[pin], wireMap, blockMap);

      // Return the new BlackBox
      return new BlackBox({pins: pins, queue: this._updateQueue.duplicate()});
    };
  }());
  P.update = function(pin){

    // A connected wire value changed

    // Check updating flag
    if (this._updating){

      // Add update to queue and return
      this._updateQueue.push(pin);
      return;
    }
    else
      this._updating = true; // Set updating flag

    // Main loop
    while (true){

      // Defensive copy external wires
      // Internal wires should never change
      var internalWires = this._internalWires, externalWires = {};
      for (var name in internalWires){

        if (this._externalWires[name])
          externalWires[name] = this._externalWires[name];
      }

      // Get updated pin value
      var value;
      if(externalWires[pin])
        value = externalWires[pin].value();
      else
        value = getUndefined();

      // Fire update event
      this.fire("update", {pin: pin, value: value});

      // Clear last error, if any
      delete this._lastError;

      // Copy values from external wires to internal wires
      for (var name in internalWires){

        if (externalWires[name])
          internalWires[name].value(externalWires[name].value());
        else
          internalWires[name].value(getUndefined());
      }

      // Handle successful run
      if (!hasOwnProperty(this, "_lastError")){

        // Fire event
        this.fire("success");

        // Copy values from internal wires to external wires
        for (var name in internalWires){

          if (externalWires[name])
            externalWires[name].value(internalWires[name].value());
        }
      }
      else
        this.fire("error", this._lastError); // Fire event

      // Proces update queue
      if (this._updateQueue.isEmpty()){

        // Unset updating flag and return
        this._updating = false;
        return;
      }
      else
        pin = this._updateQueue.next(); // Get next updated pin from queue

      // Restart loop
    }
  };
  return BlackBox;
}(this.EventEmitter, this.extendClass, this.hasOwnProperty, this.Queue, this.getUndefined, this.Map, this.Set));

<|endoftext|>


<commit_before>/**
 * This module is the main article services. It servas all actions tho the db and file connector.
 *
 * @module lib/router/article
 * @author Martin Starman, Vladislav Chumak
 */

'use strict';

var asyncLib = require('async');
var fileSystemConnector = require('../data_connection/file_system_connector');
var databaseConnector = require('../data_connection/database_connector');
var searchEngineConnector = require('../data_connection/search_engine_connector');
var config = require('../config/config');
var path = require('path');
var PromiseLib = require("promise");

var articleService = module.exports = {};

/**
 * "createArticle" creates an empty article document in the mongodb
 *
 * @function createArticle
 * @static
 *
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema|Error>} empty Article
 */
articleService.createArticle = function () {
    return databaseConnector.createArticle();
};

/**
 * "saveArticle" saves the content article in the file and ith the DB. The content gets wraps the actual text in
 * a HTML body and puts the title in the HTML head. If the article is temporary the files get copied from
 * the temp folder to the active folder.
 *
 * @param {module:lib/data_connector/models~ArticleSchema} article - current mongoDB object
 * @param {string} content - text of the article as html
 * @param {string} title - article content
 * @param {object} author - last changing author
 * @returns {Promise<module:lib/data_connector/models~ArticleSchema|Error>}
 */
articleService.saveArticle = function (article, title, content, author) {
    return new PromiseLib(function (resolve, reject) {
        var authorName = '';
        var authorMail = '';
        if (author) {
            authorName = author.name || '';
            authorMail = author.email || '';
        }

        content = fileSystemConnector.wrapContentInHTMLBody(content, title);
        fileSystemConnector.saveContent(article._id, content, article.isTemporary).then(function () {
            updateArticle(article, title, authorName, authorMail);
            databaseConnector.saveArticle(article).then(resolve, reject);
            searchEngineConnector.updateIndex();
        }, reject);
    });
};

/**
 * "findArticleById" finds an article in the mongo db by the mongo _id
 *
 * @function findArticleById
 * @static
 *
 * @param {string} id -  mongoDB _id
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema|Error>} found article
 */
articleService.findArticleById = function (id) {
    return databaseConnector.findArticleById(id);
};

/**
 * "saveDocument" saves the uploaded file to the article.
 *
 * @function saveDocument
 * @static
 *
 * @param {module:lib/data_connector/models~uploadDocument} document - text of the article as html
 * @param {module:lib/data_connector/models~ArticleSchema} article
 * @returns {Promise<module:lib/data_connector/models~ArticleSchema|Error>}
 */
articleService.saveDocument = function (article, document) {
    return new PromiseLib(function (resolve, reject) {
        fileSystemConnector.saveDocument(document, article._id, article.isTemporary).then(function (storageInfo) {
            databaseConnector.addDocumentToArticle(article, storageInfo).then(resolve, reject);
            searchEngineConnector.updateIndex();
        }, reject);
    });
};

/**
 * "saveDocuments" saves the uploaded files to the article.
 *
 * @function saveDocuments
 * @static
 *
 * @param {module:lib/data_connector/models~uploadDocument[]} documents - text of the article as html
 * @param {module:lib/data_connector/models~ArticleSchema} article
 * @returns {Promise<module:lib/data_connector/models~ArticleSchema|Error>}
 */
articleService.saveDocuments = function (article, documents) {
    var storageInfoList = [];
    return new PromiseLib(function (resolve, reject) {
        asyncLib.eachSeries(documents, function (item, cb) {
            articleService.saveDocument(article, item).then(function (storageInfo) {
                storageInfoList.push(storageInfo);
                cb();
            }, cb);
        }, function (error) {
            if (!error) {
                return resolve(storageInfoList);
            }
            reject(error);
        });
    });
};

/**
 * "getArticleContent" reads an article file and returns the extracted body content
 *
 * @function getArticleContent
 * @static
 *
 * @param {string} articleId - mongoDB id
 * @returns {Promise<String|Error>} Returns an error or null
 */
articleService.getArticleContent = function (articleId) {
    return new PromiseLib(function(resolve) {
        fileSystemConnector.readArticleContent(articleId).then(function(content) {
            resolve(content);
        }, function() {
            resolve('');
        });
    });
};

/**
 * "getOldArticleContentAndTitle" reads an old article file and returns the extracted body content
 *
 * @function getOldArticleContentAndTitle
 * @static
 *
 * @param {string} articleId - mongoDB id
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema|Error>} Returns an error or null
 */
articleService.getOldArticleContentAndTitle = function(articleId) {
    return new PromiseLib(function(resolve) {
        fileSystemConnector.readOldArticleContentAndTitle(articleId).then(function(contentAndTitle) {
            resolve(contentAndTitle);
        }, function() {
            resolve('');
        });
    });
};

/**
 * "deleteArticles" deletes an article
 *
 * @function deleteArticles
 * @static
 *
 * @param {string} articleId - mongo DB id
 * @returns {*|exports|module.exports}
 */
articleService.deleteArticle = function(articleId){
    var promiseList = [
        fileSystemConnector.deleteArticle(articleId),
        databaseConnector.deleteArticles(articleId)
    ];

    return PromiseLib.all(promiseList).then(function () {
        searchEngineConnector.updateIndex();
    });
};

/**
 * "deleteDocument" removes a document form the filesystem and from the db.
 *
 * @function deleteDocument
 * @static
 *
 * @param {module:lib/search_engine_connector~ArticleSchema} article
 * @param {string} filename
 * @returns {Promise<Boolean|Error>} Returns an error or true
 */
articleService.deleteDocument = function(article, filename){
    var document = removeFileFromArticle(article, filename);
    if (!document) {
        return PromiseLib.reject(new Error('Document not found'));
    }
    var docPath = fileSystemConnector.getPathToDocumentUnsafe(article, document);

    var promiseList = [
        fileSystemConnector.deleteDocument(docPath),
        databaseConnector.saveArticle(article)
    ];

    return PromiseLib.all(promiseList).then(function () {
        searchEngineConnector.updateIndex();
    });
};

function updateArticle(article, title, authorName, authorMail) {
        article.title = title;
        if (!article.author.name && !article.author.email) {
            article.author.name = authorName;
            article.author.email = authorMail;
        }

        article.lastChangedBy.name = authorName;
        article.lastChangedBy.email = authorMail;
        if(article.isTemporary) {
            article.isTemporary = false;
            article.documents.forEach(function (document) {
                document.path = path.join(config.fileLinkPrefixPerm, article._id + '', document.name + '.' + document.filetype).replace(/[\\]/g, '/');
            });
        }
}

function removeFileFromArticle(article, filename) {
    var hasFound = false;
    article.documents.forEach(function(document, idx) {
        var tempFilename = document.name + "." + document.filetype;
        if(filename === tempFilename) {
            hasFound = document;
            var tempDocument = article.documents.pop();
            if(idx !== article.documents.length) {
                article.documents[idx] = tempDocument;
            }

            return false;
        }
    });

    if(hasFound && article.hasOwnProperty("markModified")) {
        article.markModified('documents');
    }

    return hasFound;
}

/**
 * "searchArticles" sends an query to the OSS and sends response.
 *
 * @function searchArticles
 * @static
 *
 * @param {string} q - search query
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema[]|Error>} pass the deleteTemporaryArticlesOlderThan Promise
 */
articleService.searchArticles = function (q) {
    return new PromiseLib(function (resolve, reject) {
        // captures author:foobar and author:'foo bar'
        var author = q.match(/author:('.+?'|".+?"|[^\s'"]+)/i);
        var onlyAuthor = q.trim().match(/^author:(?:'.+?'|".+?"|[^\s'"]+)$/i);
        // remove author from search terms
        var search = q.replace(/(author:(?:'.*?'|".*?"|[^\s'"]+))/ig, '').trim();

        if (author) {
            author = author[1].replace(/["']/g, '').trim();
            if (author === '' || author.length > config.postBodyValidationValues.maxArticleAuthorNameLength) {
                return reject(new Error('Invalid author length'));
            }
        }

        if (!onlyAuthor) {
            if (search === '') {
                return reject(new Error('Search query may not be empty'));
            }
            searchEngineConnector.searchArticles(search).then(function (searchResults) {
                if (searchResults.length === 0) {
                    return resolve(searchResults);
                }

                var ids = [];
                searchResults.forEach(function (searchResult) {
                    if (ids.indexOf(searchResult.id) < 0) {
                        ids.push(searchResult.id);
                    }
                });

                databaseConnector.findArticlesByIds(ids).then(function (articles) {
                    // sort articles like search results
                    articles = articles.sort(function (a, b) {
                        return ids.indexOf(a._id + '') - ids.indexOf(b._id + '');
                    });

                    // filter articles by author
                    if (author) {
                        var authorRegExp = new RegExp('.*' + author + '.*', 'i');
                        articles.forEach(function (article, id) {
                            if (!article.author.name.match(authorRegExp) && !article.lastChangedBy.name.match(authorRegExp)) {
                                articles.splice(id, 1);
                            }
                        });
                    }

                    var promiseList = [];

                    // map search results to articles
                    articles.forEach(function (article) {
                        searchResults.forEach(function (searchResult) {
                            if (article._id + '' === searchResult.id) {
                                if (searchResult.filename === config.articleContentFileName) {
                                    if (searchResult.text) {
                                        article.text = searchResult.text;
                                    } else {
                                        promiseList.push(fileSystemConnector.readArticleContent(article._id).then(function (content) {
                                            article.text = content.substring(0, 200);
                                        }));
                                    }
                                } else {
                                    article.documents.forEach(function (document) {
                                        if (document.name + '.' + document.filetype === searchResult.filename) {
                                            document.containsSearchText = true;
                                            if (!article.text) {
                                                article.text = searchResult.text;
                                            }
                                        }
                                    });
                                }
                            }
                        });
                    });

                    if (promiseList.length > 0) {
                        PromiseLib.all(promiseList).then(function (result) {
                            resolve(articles);
                        });
                    } else {
                        resolve(articles);
                    }
                }, reject);
            });
        } else { //onlyAuthor
            databaseConnector.findArticlesByAuthor(author).then(function (articles) {
                var promiseList = [];

                articles.forEach(function (article) {
                    promiseList.push(fileSystemConnector.readArticleContent(article._id).then(function (content) {
                        article.text = content.substring(0, 200);
                    }));
                });

                if (promiseList.length > 0) {
                    PromiseLib.all(promiseList).then(function (result) {
                        resolve(articles);
                    });
                } else {
                    resolve(articles);
                }
            });
        }
    });
};

/**
 * "getArticlesByIds" finds a list of articles in the mongo db by the mongo _id
 *
 * @function getArticlesByIds
 * @static
 *
 * @param {string[]} ids -  mongoDB _id list
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema[]|Error>} found articles
 */
articleService.getArticlesByIds = function (ids) {
    return new PromiseLib(function (resolve, reject) {
        databaseConnector.findArticlesByIds(ids).then(function (articles) {
            var promiseList = [];

            articles.forEach(function (article) {
                promiseList.push(fileSystemConnector.readArticleContent(article._id).then(function (content) {
                    article.text = content.substring(0, 200);
                }));
            });

            if (promiseList.length > 0) {
                PromiseLib.all(promiseList).then(function (result) {
                    resolve(articles);
                });
            } else {
                resolve(articles);
            }
        });
    });
};

/**
 * "deleteEmptyArticles" deletes all articles in the db if file dose not exists.
 *
 * @function "deleteEmptyArticles"
 * @static
 *
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema[]|Error>} pass the findAllPermArticleIds Promise
 */
articleService.deleteEmptyArticles = function(){
    databaseConnector.findAllPermArticleIds().then(function (articleIds) {
        articleIds.forEach(function (articleId) {
            fileSystemConnector.isArticleFileExists(articleId).then(function(exists){
                if(!exists) {
                    return databaseConnector.deleteArticles(articleId);
                }
            });
        });

    });
};

/**
 * "deleteTemporaryArticles" deletes all old temp articles. Max age gets set in the config.
 *
 * @function "deleteTemporaryArticles"
 * @static
 *
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema[]|Error>} pass the deleteTemporaryArticlesOlderThan Promise
 */
articleService.deleteTemporaryArticles = function() {
    return databaseConnector.deleteTemporaryArticlesOlderThan(config.oldTemporaryArticlesDeleteJobOptions.maxAgeInHours).then(function (articles) {
        articles.forEach(function (article) {
            fileSystemConnector.deleteArticle(article._id).then(function () {
                },
                function (err) {
                    console.log(err);
                });
        });
        console.log(articles);
    });
};
<commit_msg>fixed KNOW-230<commit_after>/**
 * This module is the main article services. It servas all actions tho the db and file connector.
 *
 * @module lib/router/article
 * @author Martin Starman, Vladislav Chumak
 */

'use strict';

var asyncLib = require('async');
var fileSystemConnector = require('../data_connection/file_system_connector');
var databaseConnector = require('../data_connection/database_connector');
var searchEngineConnector = require('../data_connection/search_engine_connector');
var config = require('../config/config');
var path = require('path');
var PromiseLib = require("promise");

var articleService = module.exports = {};

/**
 * "createArticle" creates an empty article document in the mongodb
 *
 * @function createArticle
 * @static
 *
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema|Error>} empty Article
 */
articleService.createArticle = function () {
    return databaseConnector.createArticle();
};

/**
 * "saveArticle" saves the content article in the file and ith the DB. The content gets wraps the actual text in
 * a HTML body and puts the title in the HTML head. If the article is temporary the files get copied from
 * the temp folder to the active folder.
 *
 * @param {module:lib/data_connector/models~ArticleSchema} article - current mongoDB object
 * @param {string} content - text of the article as html
 * @param {string} title - article content
 * @param {object} author - last changing author
 * @returns {Promise<module:lib/data_connector/models~ArticleSchema|Error>}
 */
articleService.saveArticle = function (article, title, content, author) {
    return new PromiseLib(function (resolve, reject) {
        var authorName = '';
        var authorMail = '';
        if (author) {
            authorName = author.name || '';
            authorMail = author.email || '';
        }

        content = fileSystemConnector.wrapContentInHTMLBody(content, title);
        fileSystemConnector.saveContent(article._id, content, article.isTemporary).then(function () {
            updateArticle(article, title, authorName, authorMail);
            databaseConnector.saveArticle(article).then(resolve, reject);
            searchEngineConnector.updateIndex();
        }, reject);
    });
};

/**
 * "findArticleById" finds an article in the mongo db by the mongo _id
 *
 * @function findArticleById
 * @static
 *
 * @param {string} id -  mongoDB _id
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema|Error>} found article
 */
articleService.findArticleById = function (id) {
    return databaseConnector.findArticleById(id);
};

/**
 * "saveDocument" saves the uploaded file to the article.
 *
 * @function saveDocument
 * @static
 *
 * @param {module:lib/data_connector/models~uploadDocument} document - text of the article as html
 * @param {module:lib/data_connector/models~ArticleSchema} article
 * @returns {Promise<module:lib/data_connector/models~ArticleSchema|Error>}
 */
articleService.saveDocument = function (article, document) {
    return new PromiseLib(function (resolve, reject) {
        fileSystemConnector.saveDocument(document, article._id, article.isTemporary).then(function (storageInfo) {
            databaseConnector.addDocumentToArticle(article, storageInfo).then(resolve, reject);
            searchEngineConnector.updateIndex();
        }, reject);
    });
};

/**
 * "saveDocuments" saves the uploaded files to the article.
 *
 * @function saveDocuments
 * @static
 *
 * @param {module:lib/data_connector/models~uploadDocument[]} documents - text of the article as html
 * @param {module:lib/data_connector/models~ArticleSchema} article
 * @returns {Promise<module:lib/data_connector/models~ArticleSchema|Error>}
 */
articleService.saveDocuments = function (article, documents) {
    var storageInfoList = [];
    return new PromiseLib(function (resolve, reject) {
        asyncLib.eachSeries(documents, function (item, cb) {
            articleService.saveDocument(article, item).then(function (storageInfo) {
                storageInfoList.push(storageInfo);
                cb();
            }, cb);
        }, function (error) {
            if (!error) {
                return resolve(storageInfoList);
            }
            reject(error);
        });
    });
};

/**
 * "getArticleContent" reads an article file and returns the extracted body content
 *
 * @function getArticleContent
 * @static
 *
 * @param {string} articleId - mongoDB id
 * @returns {Promise<String|Error>} Returns an error or null
 */
articleService.getArticleContent = function (articleId) {
    return new PromiseLib(function(resolve) {
        fileSystemConnector.readArticleContent(articleId).then(function(content) {
            resolve(content);
        }, function() {
            resolve('');
        });
    });
};

/**
 * "getOldArticleContentAndTitle" reads an old article file and returns the extracted body content
 *
 * @function getOldArticleContentAndTitle
 * @static
 *
 * @param {string} articleId - mongoDB id
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema|Error>} Returns an error or null
 */
articleService.getOldArticleContentAndTitle = function(articleId) {
    return new PromiseLib(function(resolve) {
        fileSystemConnector.readOldArticleContentAndTitle(articleId).then(function(contentAndTitle) {
            resolve(contentAndTitle);
        }, function() {
            resolve('');
        });
    });
};

/**
 * "deleteArticles" deletes an article
 *
 * @function deleteArticles
 * @static
 *
 * @param {string} articleId - mongo DB id
 * @returns {*|exports|module.exports}
 */
articleService.deleteArticle = function(articleId){
    var promiseList = [
        fileSystemConnector.deleteArticle(articleId),
        databaseConnector.deleteArticles(articleId)
    ];

    return PromiseLib.all(promiseList).then(function () {
        searchEngineConnector.updateIndex();
    });
};

/**
 * "deleteDocument" removes a document form the filesystem and from the db.
 *
 * @function deleteDocument
 * @static
 *
 * @param {module:lib/search_engine_connector~ArticleSchema} article
 * @param {string} filename
 * @returns {Promise<Boolean|Error>} Returns an error or true
 */
articleService.deleteDocument = function(article, filename){
    var document = removeFileFromArticle(article, filename);
    if (!document) {
        return PromiseLib.reject(new Error('Document not found'));
    }
    var docPath = fileSystemConnector.getPathToDocumentUnsafe(article, document);

    var promiseList = [
        fileSystemConnector.deleteDocument(docPath),
        databaseConnector.saveArticle(article)
    ];

    return PromiseLib.all(promiseList).then(function () {
        searchEngineConnector.updateIndex();
    });
};

function updateArticle(article, title, authorName, authorMail) {
        article.title = title;
        if (!article.author.name && !article.author.email) {
            article.author.name = authorName;
            article.author.email = authorMail;
        }

        article.lastChangedBy.name = authorName;
        article.lastChangedBy.email = authorMail;
        if(article.isTemporary) {
            article.isTemporary = false;
            article.documents.forEach(function (document) {
                document.path = path.join(config.fileLinkPrefixPerm, article._id + '', document.name + '.' + document.filetype).replace(/[\\]/g, '/');
            });
        }
}

function removeFileFromArticle(article, filename) {
    var hasFound = false;
    article.documents.forEach(function(document, idx) {
        var tempFilename = document.name + "." + document.filetype;
        if(filename === tempFilename) {
            hasFound = document;
            var tempDocument = article.documents.pop();
            if(idx !== article.documents.length) {
                article.documents[idx] = tempDocument;
            }

            return false;
        }
    });

    if(hasFound && article.hasOwnProperty("markModified")) {
        article.markModified('documents');
    }

    return hasFound;
}

/**
 * "searchArticles" sends an query to the OSS and sends response.
 *
 * @function searchArticles
 * @static
 *
 * @param {string} q - search query
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema[]|Error>} pass the deleteTemporaryArticlesOlderThan Promise
 */
articleService.searchArticles = function (q) {
    return new PromiseLib(function (resolve, reject) {
        // captures author:foobar and author:'foo bar'
        var author = q.match(/author:('.+?'|".+?"|[^\s'"]+)/i);
        var onlyAuthor = q.trim().match(/^author:(?:'.+?'|".+?"|[^\s'"]+)$/i);
        // remove author from search terms
        var search = q.replace(/(author:(?:'.*?'|".*?"|[^\s'"]+))/ig, '').trim();

        if (author) {
            author = author[1].replace(/["']/g, '').trim();
            if (author === '' || author.length > config.postBodyValidationValues.maxArticleAuthorNameLength) {
                return reject(new Error('Invalid author length'));
            }
        }

        if (!onlyAuthor) {
            if (search === '') {
                return reject(new Error('Search query may not be empty'));
            }
            searchEngineConnector.searchArticles(search).then(function (searchResults) {
                if (searchResults.length === 0) {
                    return resolve(searchResults);
                }

                var ids = [];
                searchResults.forEach(function (searchResult) {
                    if (ids.indexOf(searchResult.id) < 0) {
                        ids.push(searchResult.id);
                    }
                });

                databaseConnector.findArticlesByIds(ids).then(function (articles) {
                    // sort articles like search results
                    articles = articles.sort(function (a, b) {
                        return ids.indexOf(a._id + '') - ids.indexOf(b._id + '');
                    });

                    // filter articles by author
                    if (author) {
                        var authorRegExp = new RegExp('.*' + author + '.*', 'i');
                        articles.forEach(function (article, id) {
                            if (!article.author.name.match(authorRegExp) && !article.lastChangedBy.name.match(authorRegExp)) {
                                articles.splice(id, 1);
                            }
                        });
                    }

                    var promiseList = [];

                    // map search results to articles
                    articles.forEach(function (article) {
                        searchResults.forEach(function (searchResult) {
                            if (article._id + '' === searchResult.id) {
                                if (searchResult.filename === config.articleContentFileName) {
                                    if (searchResult.text) {
                                        article.text = searchResult.text;
                                    } else {
                                        promiseList.push(fileSystemConnector.readArticleContent(article._id).then(function (content) {
                                            article.text = content.substring(0, 200);
                                        }));
                                    }
                                } else {
                                    article.documents.forEach(function (document) {
                                        if (document.name + '.' + document.filetype === searchResult.filename) {
                                            document.containsSearchText = true;
                                            if (!article.text) {
                                                article.text = searchResult.text;
                                            }
                                        }
                                    });
                                }
                            }
                        });
                    });

                    if (promiseList.length > 0) {
                        PromiseLib.all(promiseList).then(function (result) {
                            resolve(articles);
                        });
                    } else {
                        resolve(articles);
                    }
                }, reject);
            });
        } else { //onlyAuthor
            databaseConnector.findArticlesByAuthor(author).then(function (articles) {
                var promiseList = [];

                articles.forEach(function (article) {
                    promiseList.push(fileSystemConnector.readArticleContent(article._id).then(function (content) {
                        article.text = content.substring(0, 200);
                    }));
                });

                if (promiseList.length > 0) {
                    PromiseLib.all(promiseList).then(function (result) {
                        resolve(articles);
                    });
                } else {
                    resolve(articles);
                }
            });
        }
    });
};

/**
 * "getArticlesByIds" finds a list of articles in the mongo db by the mongo _id
 *
 * @function getArticlesByIds
 * @static
 *
 * @param {string[]} ids -  mongoDB _id list
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema[]|Error>} found articles
 */
articleService.getArticlesByIds = function (ids) {
    return new PromiseLib(function (resolve, reject) {
        databaseConnector.findArticlesByIds(ids).then(function (articles) {
            var promiseList = [];

            articles.forEach(function (article) {
                promiseList.push(fileSystemConnector.readArticleContent(article._id).then(function (content) {
                    article.text = content.substring(0, 200);
                }));
            });

            if (promiseList.length > 0) {
                PromiseLib.all(promiseList).then(function (result) {
                    resolve(articles);
                });
            } else {
                resolve(articles);
            }
        });
    });
};

/**
 * "deleteEmptyArticles" deletes all articles in the db if no corresponding file exists (not even an article.html). This
 * is done in order to get rid of old articles that still exist if somebody deletes the files from disk.
 *
 * @function "deleteEmptyArticles"
 * @static
 *
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema[]|Error>} pass the findAllPermArticleIds Promise
 */
articleService.deleteEmptyArticles = function(cb){
    databaseConnector.findAllPermArticleIds().then(function (articleIds) {
        articleIds.forEach(function (articleId) {
            fileSystemConnector.isArticleFileExists(articleId).then(function(exists){
                if(!exists) {
                    databaseConnector.deleteArticles(articleId);
                }
            });
        });
        cb();
    });
};

/**
 * "deleteTemporaryArticles" deletes all old temporary articles. Max age gets set in the config.
 *
 * @function "deleteTemporaryArticles"
 * @static
 *
 * @returns {Promise<module:lib/search_engine_connector~ArticleSchema[]|Error>} pass the deleteTemporaryArticlesOlderThan Promise
 */
articleService.deleteTemporaryArticles = function() {
    return databaseConnector.deleteTemporaryArticlesOlderThan(config.oldTemporaryArticlesDeleteJobOptions.maxAgeInHours).then(function (articles) {
        articles.forEach(function (article) {
            fileSystemConnector.deleteArticle(article._id).then(function () {
                },
                function (err) {
                    console.log(err);
                });
        });
        console.log(articles);
    });
};
<|endoftext|>


<commit_before>/*
* jQuery pager plugin
* Version 1.0 (12/22/2008)
* @requires jQuery v1.2.6 or later
*
* Example at: http://jonpauldavies.github.com/JQuery/Pager/PagerDemo.html
*
* Copyright (c) 2008-2009 Jon Paul Davies
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Read the related blog post and contact the author at http://www.j-dee.com/2008/12/22/jquery-pager-plugin/
*
* This version is far from perfect and doesn't manage it's own state, therefore contributions are more than welcome!
*
* Usage: .pager({ pagenumber: 1, pagecount: 15, buttonClickCallback: PagerClickTest });
*
* Where pagenumber is the visible page number
*       pagecount is the total number of pages to display
*       buttonClickCallback is the method to fire when a pager button is clicked.
*
* buttonClickCallback signiture is PagerClickTest = function(pageclickednumber)
* Where pageclickednumber is the number of the page clicked in the control.
*
* The included Pager.CSS file is a dependancy but can obviously tweaked to your wishes
* Tested in IE6 IE7 Firefox & Safari. Any browser strangeness, please report.
*
* modified by Oszkar Nagy (oszkar@caret.cam.ac.uk) for Sakai
* modified by Simon Gaeremynck (sg555@caret.cam.ac.uk) for Sakai
*/
(function($) {

    $.fn.pager = function(options){

        var opts = $.extend({}, $.fn.pager.defaults, options);

        return this.each(function(){

            // empty out the destination element and then render out the pager with the supplied options
			var htmlparts = {};
			if (typeof options.htmlparts === "undefined") {
				htmlparts = $.fn.pager.defaults.htmlparts;
			}
            $(this).empty().append(renderpager(parseInt(options.pagenumber, 10), parseInt(options.pagecount, 10), options.buttonClickCallback, htmlparts));

        });
    };

    // render and return the pager with the supplied options
    function renderpager(pagenumber, pagecount, buttonClickCallback, htmlparts) {

        // setup $pager to hold render
        var $pager = $('

');

        // add in the previous and next buttons
        //$pager.append(renderButton('First', pagenumber, pagecount, buttonClickCallback)).append(renderButton('« Prev', pagenumber, pagecount, buttonClickCallback));

		// Without 'First' button
		$pager.append(renderButton('prev', pagenumber, pagecount, buttonClickCallback, htmlparts));

        // pager currently only handles 10 viewable pages ( could be easily parameterized, maybe in next version ) so handle edge cases
        var startPoint = 1;
        var endPoint = 5;

        if (pagenumber > 3) {
            startPoint = pagenumber - 2;
            endPoint = pagenumber + 2;
        }

        if (endPoint > pagecount) {
            startPoint = pagecount - 3;
            endPoint = pagecount;
        }

        if (startPoint < 1) {
            startPoint = 1;
        }

		// Add 3 dots divider
		var $divider_begin = $('
...
');
		$pager.append($divider_begin);

        // loop thru visible pages and render buttons
        for (var page = startPoint; page <= endPoint; page++) {

            var currentButton = $('
' + (page) + '
');

            page == pagenumber ? currentButton.addClass('pgCurrent') : currentButton.click(function() { buttonClickCallback(this.firstChild.firstChild.data); });
            currentButton.appendTo($pager);
        }

        // render in the next and last buttons before returning the whole rendered control back.
        //$pager.append(renderButton('Next »', pagenumber, pagecount, buttonClickCallback)).append(renderButton('Last', pagenumber, pagecount, buttonClickCallback));

		// Add 3 dots divider
		var $divider_end = $('
...
');
		$pager.append($divider_end);

		// without 'Last' button:
		$pager.append(renderButton('next', pagenumber, pagecount, buttonClickCallback, htmlparts));

		if (startPoint > 1)
			{
				$divider_begin.removeClass('hidden');
			}

		if (pagecount > endPoint)
			{
				$divider_end.removeClass('hidden');
			}

			/*
			 *

 Prev

...

1

2

3

4

5

...

Next

			 *
			 */

		//prompt('', $pager.html());
        return $pager;
    }

    // renders and returns a 'specialized' button, ie 'next', 'previous' etc. rather than a page number button
    function renderButton(part, pagenumber, pagecount, buttonClickCallback, htmlparts) {

		var buttonLabel = htmlparts[part];

        var $Button = $('
' + buttonLabel + '
');

        var destPage = 1;

        // work out destination page for required button type
        switch (part) {
            case "first":
                destPage = 1;
                break;
            case "prev":
                destPage = pagenumber - 1;
				$Button = $('
' + buttonLabel + '
');
                break;
            case "next":
                destPage = pagenumber + 1;
                break;
            case "last":
                destPage = pagecount;
                break;
        }

        // disable and 'grey' out buttons if not needed.
        if (part === "first" || part === "prev") {
            pagenumber <= 1 ? $Button.addClass('pgEmpty') : $Button.click(function() { buttonClickCallback(destPage); });
        }
        else {
            pagenumber >= pagecount ? $Button.addClass('pgEmpty') : $Button.click(function() { buttonClickCallback(destPage); });
        }

        return $Button;
    }

    // pager defaults. hardly worth bothering with in this case but used as placeholder for expansion in the next version
    $.fn.pager.defaults = {
        pagenumber: 1,
        pagecount: 1,
		htmlparts : {
			'first' : 'first',
			'last' : 'last',
			'prev' : ' Prev',
			'next' : 'Next '
		}
    };

})(jQuery);<commit_msg>Pager cleanout.<commit_after>/*
* jQuery pager plugin
* Version 1.0 (12/22/2008)
* @requires jQuery v1.2.6 or later
*
* Example at: http://jonpauldavies.github.com/JQuery/Pager/PagerDemo.html
*
* Copyright (c) 2008-2009 Jon Paul Davies
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Read the related blog post and contact the author at http://www.j-dee.com/2008/12/22/jquery-pager-plugin/
*
* This version is far from perfect and doesn't manage it's own state, therefore contributions are more than welcome!
*
* Usage: .pager({ pagenumber: 1, pagecount: 15, buttonClickCallback: PagerClickTest });
*
* Where pagenumber is the visible page number
*       pagecount is the total number of pages to display
*       buttonClickCallback is the method to fire when a pager button is clicked.
*
* buttonClickCallback signiture is PagerClickTest = function(pageclickednumber)
* Where pageclickednumber is the number of the page clicked in the control.
*
* The included Pager.CSS file is a dependancy but can obviously tweaked to your wishes
* Tested in IE6 IE7 Firefox & Safari. Any browser strangeness, please report.
*
* modified by Oszkar Nagy (oszkar@caret.cam.ac.uk) for Sakai
* modified by Simon Gaeremynck (sg555@caret.cam.ac.uk) for Sakai
*/
(function($) {

    $.fn.pager = function(options){

        var opts = $.extend({}, $.fn.pager.defaults, options);

        return this.each(function(){

            // empty out the destination element and then render out the pager with the supplied options
			var htmlparts = {};
			if (typeof options.htmlparts === "undefined") {
				htmlparts = $.fn.pager.defaults.htmlparts;
			}
            $(this).empty().append(renderpager(parseInt(options.pagenumber, 10), parseInt(options.pagecount, 10), options.buttonClickCallback, htmlparts));

        });
    };

    // render and return the pager with the supplied options
    function renderpager(pagenumber, pagecount, buttonClickCallback, htmlparts) {

        // setup $pager to hold render
        var $pager = $('

');

        // add in the previous and next buttons
        //$pager.append(renderButton('First', pagenumber, pagecount, buttonClickCallback)).append(renderButton('« Prev', pagenumber, pagecount, buttonClickCallback));

		// Without 'First' button
		$pager.append(renderButton('prev', pagenumber, pagecount, buttonClickCallback, htmlparts));

        // pager currently only handles 10 viewable pages ( could be easily parameterized, maybe in next version ) so handle edge cases
        var startPoint = 1;
        var endPoint = 5;

        if (pagenumber > 3) {
            startPoint = pagenumber - 2;
            endPoint = pagenumber + 2;
        }

        if (endPoint > pagecount) {
            startPoint = pagecount - 3;
            endPoint = pagecount;
        }

        if (startPoint < 1) {
            startPoint = 1;
        }

		// Add 3 dots divider
		var $divider_begin = $('
...
');
		$pager.append($divider_begin);

        // loop thru visible pages and render buttons
        for (var page = startPoint; page <= endPoint; page++) {

            var currentButton = $('
' + (page) + '
');

            page == pagenumber ? currentButton.addClass('pgCurrent') : currentButton.click(function() { buttonClickCallback(this.firstChild.firstChild.data); });
            currentButton.appendTo($pager);
        }

        // render in the next and last buttons before returning the whole rendered control back.
        //$pager.append(renderButton('Next »', pagenumber, pagecount, buttonClickCallback)).append(renderButton('Last', pagenumber, pagecount, buttonClickCallback));

		// Add 3 dots divider
		var $divider_end = $('
...
');
		$pager.append($divider_end);

		// without 'Last' button:
		$pager.append(renderButton('next', pagenumber, pagecount, buttonClickCallback, htmlparts));

		if (startPoint > 1)
			{
				$divider_begin.removeClass('hidden');
			}

		if (pagecount > endPoint)
			{
				$divider_end.removeClass('hidden');
			}

        return $pager;
    }

    // renders and returns a 'specialized' button, ie 'next', 'previous' etc. rather than a page number button
    function renderButton(part, pagenumber, pagecount, buttonClickCallback, htmlparts) {

		var buttonLabel = htmlparts[part];

        var $Button = $('
' + buttonLabel + '
');

        var destPage = 1;

        // work out destination page for required button type
        switch (part) {
            case "first":
                destPage = 1;
                break;
            case "prev":
                destPage = pagenumber - 1;
				$Button = $('
' + buttonLabel + '
');
                break;
            case "next":
                destPage = pagenumber + 1;
                break;
            case "last":
                destPage = pagecount;
                break;
        }

        // disable and 'grey' out buttons if not needed.
        if (part === "first" || part === "prev") {
            pagenumber <= 1 ? $Button.addClass('pgEmpty') : $Button.click(function() { buttonClickCallback(destPage); });
        }
        else {
            pagenumber >= pagecount ? $Button.addClass('pgEmpty') : $Button.click(function() { buttonClickCallback(destPage); });
        }

        return $Button;
    }

    // pager defaults. hardly worth bothering with in this case but used as placeholder for expansion in the next version
    $.fn.pager.defaults = {
        pagenumber: 1,
        pagecount: 1,
		htmlparts : {
			'first' : 'first',
			'last' : 'last',
			'prev' : ' Prev',
			'next' : 'Next '
		}
    };

})(jQuery);<|endoftext|>


<commit_before>const {writeLine} = require('../csvFile')
const config = require('../server/init/configuration')
const Promise = require('bluebird')
const fs = require('fs')
const readFile = Promise.promisify(fs.readFile)
const log = require('../server/init/logging')

module.exports = function createCsvFile (msg, sisCourseCodes, csvDir, csvVol) {
  let userType = msg._desc.userType

  const fileName = `${config.full.localFile.csvDir}enrollments.${userType}.${sisCourseCodes[0]}.${Date.now()}.csv`
  // Make sure that sisCourseCodes is an array, which makes the rest of this function simpler
  if (!Array.isArray(sisCourseCodes)) {
    sisCourseCodes = [sisCourseCodes]
  }

  // create one line per sisCourseId, per user. One user can be enrolled to multiple courses, for instance if this is re-registered students
  function oneLinePerSisCourseId (userId) {
    return sisCourseCodes.forEach(sisCourseId => writeLine([sisCourseId, userId, userType, 'active'], fileName))
  }

  return writeLine(['section_id', 'user_id', 'role', 'status'], fileName)
  .then(() => Promise.map(msg.member, oneLinePerSisCourseId))
  .then(() => readFile(fileName, 'utf8'))
  .then(data => {
    log.info('Wrote file', fileName)
    log.info(data)
  })
  .then(() => { return {name: fileName} })
}
<commit_msg>log content of created csv file<commit_after>const {writeLine} = require('../csvFile')
const config = require('../server/init/configuration')
const Promise = require('bluebird')
const fs = require('fs')
const readFile = Promise.promisify(fs.readFile)
const log = require('../server/init/logging')

module.exports = function createCsvFile (msg, sisCourseCodes, csvDir, csvVol) {
  let userType = msg._desc.userType

  const fileName = `${config.full.localFile.csvDir}enrollments.${userType}.${sisCourseCodes[0]}.${Date.now()}.csv`
  // Make sure that sisCourseCodes is an array, which makes the rest of this function simpler
  if (!Array.isArray(sisCourseCodes)) {
    sisCourseCodes = [sisCourseCodes]
  }

  // create one line per sisCourseId, per user. One user can be enrolled to multiple courses, for instance if this is re-registered students
  function oneLinePerSisCourseId (userId) {
    return sisCourseCodes.forEach(sisCourseId => writeLine([sisCourseId, userId, userType, 'active'], fileName))
  }

  return writeLine(['section_id', 'user_id', 'role', 'status'], fileName)
  .then(() => Promise.map(msg.member, oneLinePerSisCourseId))
  .then(() => readFile(fileName, 'utf8'))
  .then(data => {
    log.info('Wrote file', fileName, '\n', data)
  })
  .then(() => { return {name: fileName} })
}
<|endoftext|>


<commit_before>$(document).ready(function() {
	$( "#venues-search-txt" ).autocomplete({
		minLength: 2,
		appendTo: "#venues-search-results",
		source: function(request, response) {
  	  $.ajax({
        url: "/venues/search",
        dataType: "json",
        data: {
            term: request.term
        },
        success: function(data) {
	        response($.map(data, function(item) {
	          console.log(data)
	          return {
	            label: item.name,
	            value: item.name,
	            id: item.id
	          };
	        }))
	    	}
			})
	  },
	  select: function(event, ui) {
	  	$target = $(event.target)
	  	$('#venue-query').val(ui.item.value);
	  },
	  focus: function(event, ui) {
	  	$('.ui-menu-item').css('background-color', "white");
	  	$('.ui-menu-item').css('color', "green");
	  	$('.ui-state-focus').css('background-color', "green");
	  	$('.ui-state-focus').css('color', "white");
    }
	})
	// $('ul.ui-autocomplete').removeAttr('style');
	// $('.ui-menu-item').css("background-color", "yellow");
	// $("#venues-search-results ul li").hover(function(event){
	// 	// debugger;
	// 	hovered_div = event.target
	// 	$(hovered_div).css("background-color","yellow");
	// })

	// $("#venue-search-button").on('click', function(event) {
		// event.preventDefault();
		// alert('click!');
	// })
  $('#venues-search-form').on('submit', function(event) {
  	event.preventDefault();
    $target = $(event.target)
    $.ajax({
      url: $target.attr('href'),
      data: $target.serialize()
    }).done(function(response){
    	console.log(response);
      $('#venue-index-main').html(response);
    })
  })
});
<commit_msg>update ids to work with same search form on multiple pages<commit_after>$(document).ready(function() {
	$( "#search-txt" ).autocomplete({
		minLength: 2,
		appendTo: "#search-results",
		source: function(request, response) {
  	  $.ajax({
        url: $('#search-form').attr("action"),
        dataType: "json",
        data: {
            term: request.term
        },
        success: function(data) {
	        response($.map(data, function(item) {
	          // console.log(data)
	          return {
	            label: item.name,
	            value: item.name,
	            id: item.id
	          };
	        }))
	    	}
			})
	  },
	  // select: function(event, ui) {
	  	// $target = $(event.target)
	  	// debugger;
	  	// $('#venue-query').val(ui.item.value);
	  // },
	  focus: function(event, ui) {
	  	$('.ui-menu-item').css('background-color', "white");
	  	$('.ui-menu-item').css('color', "green");
	  	$('.ui-state-focus').css('background-color', "green");
	  	$('.ui-state-focus').css('color', "white");
    }
	})
  $('#search-form').on('submit', function(event) {
  	event.preventDefault();
    $target = $(event.target)
    $.ajax({
      url: $target.attr('href'),
      data: $target.serialize()
    }).done(function(response){
    	// console.log(response);
      $('.index-main').html(response);
    })
  })
});
<|endoftext|>


<commit_before>"use strict";

const plugin_manager = function (config, configPath) {
  const path = require('path');
  const fs = require('fs-extra');
  const util = require('./utilities');

  /**
   * Loads a plugin
   *
   * @param pluginName {string} the name of the plugin
   * @return {object} the loaded plugin
   */
  function loadPlugin(pluginName) {
    return require(path.join(process.cwd(), 'node_modules', pluginName));
  }

  /**
   * Installs a plugin
   *
   * @param pluginName {string} the name of the plugin
   */
  function installPlugin(pluginName) {
    try {
      const pluginPath = path.resolve(
        path.join(process.cwd(), 'node_modules', pluginName)
      );
      console.log('Attempting to load plugin from', pluginPath);
      try {
        var pluginDirStats = fs.statSync(pluginPath);
      } catch (ex) {
        util.error(pluginName + ' not found, please use npm to install it first.');
        util.error(pluginName + ' not loaded.');
        return;
      }
      const pluginPathDirExists = pluginDirStats.isDirectory();
      if (pluginPathDirExists) {

        const diskConfig = fs.readJSONSync(path.resolve(configPath), 'utf8');

        //add the plugin entry to patternlab-config.json
        if (!diskConfig.plugins) {
          diskConfig.plugins = {};
        }

        if (!diskConfig.plugins[pluginName]) {
          diskConfig.plugins[pluginName] = {
            enabled: true,
            initialized: false
          };
        }

        const pluginPathConfig = path.resolve(pluginPath, 'config.json');
        try {
          var pluginConfigJSON = require(pluginPathConfig);
          if (!diskConfig.plugins[pluginName].options) {
            diskConfig.plugins[pluginName].options = pluginConfigJSON;
          }
        } catch (ex) {
          //a config.json file is not required at this time
        }

        //write config entry back
        fs.outputFileSync(path.resolve(configPath), JSON.stringify(diskConfig, null, 2));

        util.debug('Plugin ' + pluginName + ' installed.');

        //todo, tell them how to uninstall or disable

      }
    } catch (ex) {
      console.log(ex);
    }
  }

  /**
   * Detect installed plugins
   *
   * @return {array} list of installed plugins
   */
  function detectPlugins() {
    const node_modules_path = path.join(process.cwd(), 'node_modules');
    return fs.readdirSync(node_modules_path).filter(function (dir) {
      const module_path = path.join(process.cwd(), 'node_modules', dir);
      return fs.statSync(module_path).isDirectory() && dir.indexOf('plugin-node-') === 0;
    });
  }

  /**
   * Disables an installed plugin
   * Not implemented yet
   */
  function disablePlugin(pluginName) {
    console.log('disablePlugin not implemented yet. No change made to state of plugin', pluginName);
  }

  /**
   * Enables an installed plugin
   * Not implemented yet
   */
  function enablePlugin(pluginName) {
    console.log('enablePlugin not implemented yet. No change made to state of plugin', pluginName);
  }

  return {
    install_plugin: function (pluginName) {
      installPlugin(pluginName);
    },
    load_plugin: function (pluginName) {
      return loadPlugin(pluginName);
    },
    detect_plugins: function () {
      return detectPlugins();
    },
    disable_plugin: function (pluginName) {
      disablePlugin(pluginName);
    },
    enable_plugin: function (pluginName) {
      enablePlugin(pluginName);
    }
  };

};

module.exports = plugin_manager;
<commit_msg>feat(logs): Refactor logs for plugin_manager<commit_after>"use strict";

const plugin_manager = function (config, configPath) {
  const path = require('path');
  const fs = require('fs-extra');
  const logger = require('./log');

  /**
   * Loads a plugin
   *
   * @param pluginName {string} the name of the plugin
   * @return {object} the loaded plugin
   */
  function loadPlugin(pluginName) {
    return require(path.join(process.cwd(), 'node_modules', pluginName));
  }

  /**
   * Installs a plugin
   *
   * @param pluginName {string} the name of the plugin
   */
  function installPlugin(pluginName) {
    try {
      const pluginPath = path.resolve(
        path.join(process.cwd(), 'node_modules', pluginName)
      );
      logger.debug(`Attempting to load plugin from ${pluginPath}`);
      try {
        var pluginDirStats = fs.statSync(pluginPath);
      } catch (ex) {
        logger.warning(`${pluginName} not found, use npm to install it first.`);
        logger.warning(`${pluginName} not loaded.`);
        return;
      }
      const pluginPathDirExists = pluginDirStats.isDirectory();
      if (pluginPathDirExists) {

        const diskConfig = fs.readJSONSync(path.resolve(configPath), 'utf8');

        //add the plugin entry to patternlab-config.json
        if (!diskConfig.plugins) {
          diskConfig.plugins = {};
        }

        if (!diskConfig.plugins[pluginName]) {
          diskConfig.plugins[pluginName] = {
            enabled: true,
            initialized: false
          };
        }

        const pluginPathConfig = path.resolve(pluginPath, 'config.json');
        try {
          var pluginConfigJSON = require(pluginPathConfig);
          if (!diskConfig.plugins[pluginName].options) {
            diskConfig.plugins[pluginName].options = pluginConfigJSON;
          }
        } catch (ex) {
          //a config.json file is not required at this time
        }

        //write config entry back
        fs.outputFileSync(path.resolve(configPath), JSON.stringify(diskConfig, null, 2));

        logger.info('Plugin ' + pluginName + ' installed.');
        logger.info('Plugin configration added to patternlab-config.json.');
      }
    } catch (ex) {
      logger.warning(`An error occurred during plugin installation for plugin ${pluginName}`);
      logger.warning(ex);
    }
  }

  /**
   * Detect installed plugins
   *
   * @return {array} list of installed plugins
   */
  function detectPlugins() {
    const node_modules_path = path.join(process.cwd(), 'node_modules');
    return fs.readdirSync(node_modules_path).filter(function (dir) {
      const module_path = path.join(process.cwd(), 'node_modules', dir);
      return fs.statSync(module_path).isDirectory() && dir.indexOf('plugin-node-') === 0;
    });
  }

  /**
   * Disables an installed plugin
   * Not implemented yet
   */
  function disablePlugin(pluginName) {
    logger.warning(`disablePlugin() not implemented yet. No change made to state of plugin ${pluginName}`);
  }

  /**
   * Enables an installed plugin
   * Not implemented yet
   */
  function enablePlugin(pluginName) {
    logger.warning(`enablePlugin() not implemented yet. No change made to state of plugin ${pluginName}`);
  }

  return {
    install_plugin: function (pluginName) {
      installPlugin(pluginName);
    },
    load_plugin: function (pluginName) {
      return loadPlugin(pluginName);
    },
    detect_plugins: function () {
      return detectPlugins();
    },
    disable_plugin: function (pluginName) {
      disablePlugin(pluginName);
    },
    enable_plugin: function (pluginName) {
      enablePlugin(pluginName);
    }
  };

};

module.exports = plugin_manager;
<|endoftext|>


<commit_before>function $JsCallable(callable,parms,targs) {
    if (callable.getT$all === undefined) {
        callable.getT$all=Callable.getT$all;
    }
    var set_meta = callable.$crtmm$ === undefined;
    if (set_meta) {
        callable.$crtmm$={ps:[],mod:$CCMM$,d:['$','Callable']};
        if (parms !== undefined) {
            callable.$crtmm$['ps']=parms;
        }
    }
    if (targs !== undefined && callable.$$targs$$ === undefined) {
        callable.$$targs$$=targs;
        if (set_meta) {
            callable.$crtmm$['$t']=targs['Return'];
        }
    }
    return callable;
}
initExistingTypeProto($JsCallable, Function, 'ceylon.language::JsCallable', Callable);

function nop$() { return null; }

//This is used for plain method references
function JsCallable(o,f) {
  if (o===null || o===undefined) return nop$;
  var f2 = function() {
    var arg=[].slice.call(arguments,0);
    if (arg.length==1 && is$(arg[0],{t:Tuple})) {
      //Possible spread
      var mm=getrtmm$$(f);
      var typecheck={t:Iterable};
      if (arg[0].$$targs$$ && arg[0].$$targs$$.Element$Iterable)typecheck.a={Element$Iterable:arg[0].$$targs$$.Element$Iterable};
      if (mm && mm.ps!==undefined
          && (mm.ps.length>1 || (mm.ps.length==1
          && (mm.ps[0].seq || !extendsType(mm.ps[0].$t, typecheck))))) {
        var a=arg[0].elem$;
        if (a===undefined) {
          a=[];
          for (var i=0;i<arg[0].size;i++)a.push(arg[0].$_get(i));
        }
        arg=a;
      }
    }
    return f.apply(o, arg);
  };
  f2.$crtmm$=f.$crtmm$===undefined?Callable.$crtmm$:f.$crtmm$;
  return f2;
}
JsCallable.$crtmm$=function(){return{ sts:[{t:Callable,a:{Return$Callable:'Return$Callable',Arguments$Callable:'Arguments$Callable'}}],
  tp:{Return$Callable:{dv:'out'}, Arguments$Callable:{dv:'in'}},pa:1,mod:$CCMM$,d:['$','Callable']};}

//This is used for spread method references
function JsCallableList(value) {
    return function() {
        var rval = Array(value.length);
        for (var i = 0; i < value.length; i++) {
            var c = value[i];
            rval[i] = c.f.apply(c.o, arguments);
        }
        return value.length===0?getEmpty():sequence(rval,{Element$sequence:{t:Callable},Absent$sequence:{t:Nothing}});
    };
}
JsCallableList.$crtmm$={tp:{Return$Callable:{dv:'out'}, Arguments$Callable:{dv:'in'}},pa:1,mod:$CCMM$,d:['$','Callable']};

ex$.JsCallableList=JsCallableList;
ex$.JsCallable=JsCallable;
ex$.$JsCallable=$JsCallable;
<commit_msg>part of ceylon/ceylon-js#436<commit_after>function $JsCallable(callable,parms,targs) {
    if (callable.getT$all === undefined) {
        callable.getT$all=Callable.getT$all;
    }
    var set_meta = callable.$crtmm$ === undefined;
    if (set_meta) {
        callable.$crtmm$={ps:[],mod:$CCMM$,d:['$','Callable']};
        if (parms !== undefined) {
            callable.$crtmm$['ps']=parms;
        }
    }
    if (targs !== undefined && callable.$$targs$$ === undefined) {
        callable.$$targs$$=targs;
        if (set_meta) {
            callable.$crtmm$['$t']=targs['Return'];
        }
    }
    return callable;
}
initExistingTypeProto($JsCallable, Function, 'ceylon.language::JsCallable', Callable);

function nop$() { return null; }

//This is used for plain method references
function JsCallable(o,f) {
  if (o===null || o===undefined) return nop$;
  var f2 = function() {
    var arg=[].slice.call(arguments,0);
    if (arg.length==1 && is$(arg[0],{t:Tuple})) {
      //Possible spread
      var mm=getrtmm$$(f);
      var typecheck={t:Iterable};
      if (arg[0].$$targs$$ && arg[0].$$targs$$.Element$Iterable)typecheck.a={Element$Iterable:arg[0].$$targs$$.Element$Iterable};
      if (mm && mm.ps!==undefined
          && (mm.ps.length>1 || (mm.ps.length==1
          && (mm.ps[0].seq || !extendsType(mm.ps[0].$t, typecheck))))) {
        var a=arg[0].elem$;
        if (a===undefined) {
          a=[];
          for (var i=0;i<arg[0].size;i++)a.push(arg[0].$_get(i));
        }
        arg=a;
      }
    }
    return f.apply(o, arg);
  };
  f2.$crtmm$=f.$crtmm$===undefined?Callable.$crtmm$:f.$crtmm$;
  return f2;
}
JsCallable.$crtmm$=function(){return{ sts:[{t:Callable,a:{Return$Callable:'Return$Callable',Arguments$Callable:'Arguments$Callable'}}],
  tp:{Return$Callable:{dv:'out'}, Arguments$Callable:{dv:'in'}},pa:1,mod:$CCMM$,d:['$','Callable']};}

//This is used for spread method references
function JsCallableList(value,$mpt) {
    return function() {
        var a=arguments;
        if ($mpt) {
          a=[].slice.call(arguments,0);
          a.push($mpt);
        }
        var rval = Array(value.length);
        for (var i = 0; i < value.length; i++) {
            var c = value[i];
            rval[i] = c.f.apply(c.o, a);
        }
        return value.length===0?getEmpty():sequence(rval,{Element$sequence:{t:Callable},Absent$sequence:{t:Nothing}});
    };
}
JsCallableList.$crtmm$={tp:{Return$Callable:{dv:'out'}, Arguments$Callable:{dv:'in'}},pa:1,mod:$CCMM$,d:['$','Callable']};

ex$.JsCallableList=JsCallableList;
ex$.JsCallable=JsCallable;
ex$.$JsCallable=$JsCallable;
<|endoftext|>


<commit_before>/**********************************************************************
    Freeciv-web - the web version of Freeciv. http://play.freeciv.org/
    Copyright (C) 2009-2015  The Freeciv-web project

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

***********************************************************************/

/****************************************************************************
 ...
****************************************************************************/
function clone(obj){
  if(obj == null || typeof(obj) != 'object') {
    return obj;
  }
  var temp = obj.constructor(); // changed

  for (var key in obj) {
    temp[key] = clone(obj[key]);
  }

  return temp;
}

/*
 * DIVIDE() divides and rounds down, rather than just divides and
 * rounds toward 0.  It is assumed that the divisor is positive.
 */
function DIVIDE (n, d) {
  return parseInt( (n) / (d) - (( (n) < 0 && (n) % (d) < 0 ) ? 1 : 0) );
}

/****************************************************************************
 ...
****************************************************************************/
function FC_WRAP(value, range)
{
    return ((value) < 0
     ? ((value) % (range) != 0 ? (value) % (range) + (range) : 0)
     : ((value) >= (range) ? (value) % (range) : (value)));
}

/****************************************************************************
 ...
****************************************************************************/
function XOR(a,b) {
  return ( a || b ) && !( a && b );
}

/****************************************************************************
 ...
****************************************************************************/
$.extend({
  getUrlVars: function(){
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  }
});

var benchmark_start = 0;

/****************************************************************************
 Benchmark the Freeciv.net webclient.
****************************************************************************/
function civclient_benchmark(frame)
{

  if (frame == 0) benchmark_start = new Date().getTime();

  var ptile = map_pos_to_tile(frame+5, frame+5)
  center_tile_mapcanvas(ptile);

  if (frame < 30) {
    setTimeout("civclient_benchmark(" + (frame + 1) + ");", 10);
  } else {

    var end = new Date().getTime();
    var time = (end - benchmark_start) / 25;
    swal('Redraw time: ' + time);
  }
}

/****************************************************************************
 ...
****************************************************************************/
function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

/**************************************************************************
...
**************************************************************************/
function to_title_case(str)
{
  return str.replace(/\w\S*/g,
         function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

/**************************************************************************
...
**************************************************************************/
function get_random_int(min, max) {
  return Math.floor(fc_seedrandom() * (max - min)) + min;
}

/**************************************************************************
...
**************************************************************************/
function supports_mp3() {
  var a = document.createElement('audio');
  return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
}
<commit_msg>Add string qualification removal function<commit_after>/**********************************************************************
    Freeciv-web - the web version of Freeciv. http://play.freeciv.org/
    Copyright (C) 2009-2015  The Freeciv-web project

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

***********************************************************************/

/****************************************************************************
 ...
****************************************************************************/
function clone(obj){
  if(obj == null || typeof(obj) != 'object') {
    return obj;
  }
  var temp = obj.constructor(); // changed

  for (var key in obj) {
    temp[key] = clone(obj[key]);
  }

  return temp;
}

/*
 * DIVIDE() divides and rounds down, rather than just divides and
 * rounds toward 0.  It is assumed that the divisor is positive.
 */
function DIVIDE (n, d) {
  return parseInt( (n) / (d) - (( (n) < 0 && (n) % (d) < 0 ) ? 1 : 0) );
}

/****************************************************************************
 ...
****************************************************************************/
function FC_WRAP(value, range)
{
    return ((value) < 0
     ? ((value) % (range) != 0 ? (value) % (range) + (range) : 0)
     : ((value) >= (range) ? (value) % (range) : (value)));
}

/****************************************************************************
 ...
****************************************************************************/
function XOR(a,b) {
  return ( a || b ) && !( a && b );
}

/****************************************************************************
 ...
****************************************************************************/
$.extend({
  getUrlVars: function(){
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  }
});

var benchmark_start = 0;

/****************************************************************************
 Benchmark the Freeciv.net webclient.
****************************************************************************/
function civclient_benchmark(frame)
{

  if (frame == 0) benchmark_start = new Date().getTime();

  var ptile = map_pos_to_tile(frame+5, frame+5)
  center_tile_mapcanvas(ptile);

  if (frame < 30) {
    setTimeout("civclient_benchmark(" + (frame + 1) + ");", 10);
  } else {

    var end = new Date().getTime();
    var time = (end - benchmark_start) / 25;
    swal('Redraw time: ' + time);
  }
}

/****************************************************************************
 ...
****************************************************************************/
function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

/**************************************************************************
...
**************************************************************************/
function to_title_case(str)
{
  return str.replace(/\w\S*/g,
         function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

/**************************************************************************
  Remove a string's translation qualifier.

  The Freeciv server qualifies some strings for translation purposes. The
  qualifiers shouldn't be shown to the user.
**************************************************************************/
function string_unqualify(str)
{
  if (str.charAt(0) == "?" && str.indexOf(":") != -1) {
    /* This string is qualified. Remove it. */
    return str.substr(str.indexOf(":") + 1);
  } else {
    /* This string isn't qualified. */
    return str;
  }
}

/**************************************************************************
...
**************************************************************************/
function get_random_int(min, max) {
  return Math.floor(fc_seedrandom() * (max - min)) + min;
}

/**************************************************************************
...
**************************************************************************/
function supports_mp3() {
  var a = document.createElement('audio');
  return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
}
<|endoftext|>