<commit_before>"use strict";

module.exports = class Drupal extends require('./Script') {

  /**
   * Options (used by this task):
   *   @param {object} container - An instantiated and configured Container object.
   *   @param {object} options - A hash of configuration options specific to this task.
   *   @param {boolean} options.clearCaches - Whether to clear all caches after the build is finished. Defaults to true.
   *   @param {string} options.siteFolder - The site folder to use for this build (the folder within the drupal `sites` folder).  Defaults to `default`.
   *   @param {string} options.database - The name of the database to import if specified. Note that this database *must be added to the assets array separately*.
   *   @param {boolean} options.databaseGzipped - Whether the database was sent gzipped and whether it should therefore be gunzipped before importing.
   *   @param {boolean} options.databaseUpdates - Determines whether to run `drush updb`.
   *   @param {boolean} options.revertFeatures - Whether to revert features using `drush fra`.
   *   @param {string} options.makeFile - The name of the make file to run to generate the install directory.
   *   @param {boolean} options.runInstall - If set, run `drush site-install` to perform a fresh install of the site using the profileName as the profile to install and allowing instlallArgs to configure the install.
   *   @param {string} options.profileName - The profileName, used in symlinking this directory if makeFile is specified and used to select the profile to install if `runInstall` is selected.
   *   @param {string} options.installArgs - A set of params to concat onto the drush `site-install` command (defaults to '').
   */
  constructor(container, options) {
    super(container, options);

    this.options.siteFolder = options.siteFolder || 'default';
    this.options.profileName = options.profileName || 'standard';
    this.options.clearCaches = options.clearCaches !== undefined ? options.clearCaches : true;

    // TODO: Add some kind of validation.

    // Filter out secret strings
    options.secrets = [
    ];

    var subDirectory = options.subDirectory || 'docroot';
    this.script = [];
    this.populateScriptArray();
    this.setScript(this.script);

  }

  description() {
    return `${this.plugin} 'Provisioning Drupal!'`;
  }

  /**
   *
   */
  populateScriptArray() {
    this.addScriptHeader();
    if (this.options.makeFile) {
      this.addScriptRunMakeFile();
    }
    else {
      this.addScriptSymlinks();
    }
    this.addScriptCreateDatbase();
    this.addScriptAppendSettingsPHPSettings();
    this.addScriptPublicFilesDirectory();
    if (this.options.database) {
      this.addScriptImportDatabase();
    }
    if (this.options.runInstall) {
      this.addScriptRunInstall();
    }
    if (this.options.databaseUpdates) {
      this.addScriptDatabaseUpdates();
    }
    if (this.options.revertFeatures) {
      this.addScriptRevertFeatures();
    }
    if (this.options.clearCaches) {
      this.addScriptClearCaches();
    }
  }

  addScriptHeader() {
    this.script = this.script.concat([
      'sleep 3',
    ]);
  }

  addScriptSymlinks() {
    this.script = this.script.concat([
      'if [ -d "$SRC_DIR/docroot" ] ; then',
      '  echo \'Docroot found within code directory, creating symlink.\'',
      '  ln -s "$SRC_DIR/docroot" /var/www/html',
      'fi',
      'if [ -a "$SRC_DIR/index.php" ] ; then',
      '  echo \'Index.php found within the root of the codebase, creating symlink.\'',
      '  ln -s $SRC_DIR  /var/www/html',
      'fi',
    ]);
  }

  addScriptCreateDatbase() {
    this.script = this.script.concat([
      'echo \'Creating MySQL Database, user and granting access.\'',
      'mysql -e \'create database drupal\'',
      'mysql -e \'grant all on drupal.* to "root"@"localhost"\'',
      'mysql -e \'flush privileges\'',
    ]);
  }

  addScriptAppendSettingsPHPSettings() {
    this.script = this.script.concat([
      'PHP_SNIPPET=$(cat <<END_HEREDOC',
      '\\$databases = array(',
      '  \'default\' => array(',
      '    \'default\' => array(',
      '      \'database\' => \'drupal\',',
      '      \'username\' => \'root\',',
      '      \'password\' => \'strongpassword\',',
      '      \'host\' => \'localhost\',',
      '      \'driver\' => \'mysql\',',
      '    ),',
      '  ),',
      ');',
      'END_HEREDOC',
      ')',
      'if [ ! -a "/var/www/html/sites/' + this.options.siteFolder + '/settings.php" ] ; then',
      '  echo \'<?php\n\' > /var/www/html/sites/' + this.options.siteFolder + '/settings.php',
      'fi',
      'echo "$PHP_SNIPPET" >> /var/www/html/sites/' + this.options.siteFolder + '/settings.php',
    ]);
  }

  addScriptPublicFilesDirectory() {
    this.script = this.script.concat([
      'mkdir -p /var/www/html/sites/' + this.options.siteFolder + '/files',
      'chown www-data:www-data -R /var/www/html/sites/' + this.options.siteFolder + '/files',
    ]);
  }

  addScriptImportDatabase() {
    if (this.options.database) {
      var databaseImportBase = '';
      if (this.options.databaseGzipped) {
        databaseImportBase = 'gunzip -c ';
      }
      else {
        databaseImportBase = 'cat ';
      }
      this.script.push(databaseImportBase + ' $ASSET_DIR/' + this.options.database + ' | `drush --root=/var/www/html sql-connect`');
      this.script.push('rm $ASSET_DIR/' + this.options.database);
    }
  }

  addScriptRunInstall() {
    var installArgs = this.options.installArgs || '';
    this.script.push(`drush site-install --root=/var/www/html ${this.options.profileName} ${installArgs}`);
  }

  addScriptDatabaseUpdates() {
    this.script.push('drush --root=/var/www/html updb');
  }

  addScriptRevertFeatures() {
    this.script.push('drush --root=/var/www/html fra');
  }

  addScriptRunMakeFile() {
    this.script.push('cd $SRC_DIR ; drush make ' + this.options.makeFile + ' /var/www/html --force-complete');
    this.script.push('rsync -a $SRC_DIR/ /var/www/html/profiles/' + this.options.profileName);
  }

  addScriptClearCaches() {
    this.script.push('drush --root=/var/www/html cache-clear all');
  }

};
<commit_msg>Linting Drupal.js.<commit_after>'use strict';

module.exports = class Drupal extends require('./Script') {

  /**
   * Options (used by this task):
   *   @param {object} container - An instantiated and configured Container object.
   *   @param {object} options - A hash of configuration options specific to this task.
   *   @param {boolean} options.clearCaches - Whether to clear all caches after the build is finished. Defaults to true.
   *   @param {string} options.siteFolder - The site folder to use for this build (the folder within the drupal `sites` folder).  Defaults to `default`.
   *   @param {string} options.database - The name of the database to import if specified. Note that this database *must be added to the assets array separately*.
   *   @param {boolean} options.databaseGzipped - Whether the database was sent gzipped and whether it should therefore be gunzipped before importing.
   *   @param {boolean} options.databaseUpdates - Determines whether to run `drush updb`.
   *   @param {boolean} options.revertFeatures - Whether to revert features using `drush fra`.
   *   @param {string} options.makeFile - The name of the make file to run to generate the install directory.
   *   @param {boolean} options.runInstall - If set, run `drush site-install` to perform a fresh install of the site using the profileName as the profile to install and allowing instlallArgs to configure the install.
   *   @param {string} options.profileName - The profileName, used in symlinking this directory if makeFile is specified and used to select the profile to install if `runInstall` is selected.
   *   @param {string} options.installArgs - A set of params to concat onto the drush `site-install` command (defaults to '').
   */
  constructor(container, options) {
    super(container, options);

    this.options.siteFolder = options.siteFolder || 'default';
    this.options.profileName = options.profileName || 'standard';
    this.options.clearCaches = options.clearCaches !== undefined ? options.clearCaches : true;

    // TODO: Add some kind of validation.

    // Filter out secret strings
    options.secrets = [
    ];

    var subDirectory = options.subDirectory || 'docroot';
    this.script = [];
    this.populateScriptArray();
    this.setScript(this.script);

  }

  description() {
    return `${this.plugin} 'Provisioning Drupal!'`;
  }

  /**
   *
   */
  populateScriptArray() {
    this.addScriptHeader();
    if (this.options.makeFile) {
      this.addScriptRunMakeFile();
    }
    else {
      this.addScriptSymlinks();
    }
    this.addScriptCreateDatbase();
    this.addScriptAppendSettingsPHPSettings();
    this.addScriptPublicFilesDirectory();
    if (this.options.database) {
      this.addScriptImportDatabase();
    }
    if (this.options.runInstall) {
      this.addScriptRunInstall();
    }
    if (this.options.databaseUpdates) {
      this.addScriptDatabaseUpdates();
    }
    if (this.options.revertFeatures) {
      this.addScriptRevertFeatures();
    }
    if (this.options.clearCaches) {
      this.addScriptClearCaches();
    }
  }

  addScriptHeader() {
    this.script = this.script.concat([
      'sleep 3',
    ]);
  }

  addScriptSymlinks() {
    this.script = this.script.concat([
      'if [ -d "$SRC_DIR/docroot" ] ; then',
      '  echo \'Docroot found within code directory, creating symlink.\'',
      '  ln -s "$SRC_DIR/docroot" /var/www/html',
      'fi',
      'if [ -a "$SRC_DIR/index.php" ] ; then',
      '  echo \'Index.php found within the root of the codebase, creating symlink.\'',
      '  ln -s $SRC_DIR  /var/www/html',
      'fi',
    ]);
  }

  addScriptCreateDatbase() {
    this.script = this.script.concat([
      'echo \'Creating MySQL Database, user and granting access.\'',
      'mysql -e \'create database drupal\'',
      'mysql -e \'grant all on drupal.* to "root"@"localhost"\'',
      'mysql -e \'flush privileges\'',
    ]);
  }

  addScriptAppendSettingsPHPSettings() {
    this.script = this.script.concat([
      'PHP_SNIPPET=$(cat <<END_HEREDOC',
      '\\$databases = array(',
      '  \'default\' => array(',
      '    \'default\' => array(',
      '      \'database\' => \'drupal\',',
      '      \'username\' => \'root\',',
      '      \'password\' => \'strongpassword\',',
      '      \'host\' => \'localhost\',',
      '      \'driver\' => \'mysql\',',
      '    ),',
      '  ),',
      ');',
      'END_HEREDOC',
      ')',
      'if [ ! -a "/var/www/html/sites/' + this.options.siteFolder + '/settings.php" ] ; then',
      '  echo \'<?php\n\' > /var/www/html/sites/' + this.options.siteFolder + '/settings.php',
      'fi',
      'echo "$PHP_SNIPPET" >> /var/www/html/sites/' + this.options.siteFolder + '/settings.php',
    ]);
  }

  addScriptPublicFilesDirectory() {
    this.script = this.script.concat([
      'mkdir -p /var/www/html/sites/' + this.options.siteFolder + '/files',
      'chown www-data:www-data -R /var/www/html/sites/' + this.options.siteFolder + '/files',
    ]);
  }

  addScriptImportDatabase() {
    if (this.options.database) {
      var databaseImportBase = '';
      if (this.options.databaseGzipped) {
        databaseImportBase = 'gunzip -c ';
      }
      else {
        databaseImportBase = 'cat ';
      }
      this.script.push(databaseImportBase + ' $ASSET_DIR/' + this.options.database + ' | `drush --root=/var/www/html sql-connect`');
      this.script.push('rm $ASSET_DIR/' + this.options.database);
    }
  }

  addScriptRunInstall() {
    var installArgs = this.options.installArgs || '';
    this.script.push(`drush site-install --root=/var/www/html ${this.options.profileName} ${installArgs}`);
  }

  addScriptDatabaseUpdates() {
    this.script.push('drush --root=/var/www/html updb');
  }

  addScriptRevertFeatures() {
    this.script.push('drush --root=/var/www/html fra');
  }

  addScriptRunMakeFile() {
    this.script.push('cd $SRC_DIR ; drush make ' + this.options.makeFile + ' /var/www/html --force-complete');
    this.script.push('rsync -a $SRC_DIR/ /var/www/html/profiles/' + this.options.profileName);
  }

  addScriptClearCaches() {
    this.script.push('drush --root=/var/www/html cache-clear all');
  }

};
<|endoftext|>


<commit_before>exports.createProject = function(app, mongoose, request, response, callback) {
	var heading = request.body.heading;
	var description = request.body.description;
	var owner = request.body.owner;
	var users = request.body.users;
	if (owner === '') {
		response.send(false);
		if (callback !== undefined) {
			callback();
		}
		return;
	}
	var outerScope = this;
	this.checkProject(heading, app, mongoose, function(result) {
		if (result.length >= 1) {
			//Project name already exists
			for (var i = result.length - 1; i >= 0; i--) {
				if (result[i].deleted === false) {
					response.send(false);
					if (callback !== undefined) {
						callback();
					}
					return;
				}
			}
		}

		var Project = mongoose.model('Project', app.projectSchema);

		var project = new Project({
			name : heading,
			description : description,
			children : [],
			deleted : false,
			users : users,
			owner : owner
		});
		outerScope.persistProject(project);
		response.send(project);
		if (callback !== undefined) {
			callback();
		}
	});
};

exports.checkProject = function(searchheading, app, mongoose, callback) {
	var res = null;
	var Project = mongoose.model('Project', app.projectSchema);
	Project.find({name: searchheading}, function(err, project) {
		if (err) {
			return console.error(err);
		}
		callback(project);
	});
};

exports.persistProject = function(project) {
	project.save(function(err, data) {
		if (err) {
			console.log(err);
		} else {
			// console.log('Saved : ', data);
		}
	});
};

exports.getAllProjects = function(app, mongoose, request, response, callback) {
	var Project = mongoose.model('Project', app.projectSchema);

	Project.find({deleted : 'false'}, function(err, projects) {
		if (err) {
			return console.error(err);
		}
		if (callback === undefined) {
			response.send(projects);
		} else {
			response.send(projects);
			callback(projects);
		}

	});
};

exports.getProject = function(app, mongoose, request, response, callback) {
	var searchheading = request.body.heading;
	var Project = mongoose.model('Project', app.projectSchema);

	Project.find({name: searchheading}, function(err, project) {
		if (err) {
			return console.error(err);
		}
		if (callback === undefined) {
			response.send(project);
		} else {
			response.send(project);
			callback(project);
		}
	});
};

exports.addChild = function(app, mongoose, request, response, callback) {
	var Project = mongoose.model('Project', app.projectSchema);
	var project = request.body;
	var condition = {_id : project._id};
	var update = project;
	var options = {multi: true};
	Project.update(condition, update, options, function(err, numAffected) {
		console.log(numAffected);
	});
	if (callback === undefined) {
		response.send(project);
	} else {
		response.send(project);
		callback(project);
	}
};

exports.deleteProject = function(app, mongoose, request, response) {
	var Project = mongoose.model('Project', app.projectSchema);
	var project = request.body;
	var condition = {_id : project._id};
	var update = {deleted : true};
	var options = {multi: true};
	Project.update(condition, update, options, function(err, numAffected) {
		console.log(numAffected);
	});
	response.send(true);
};
<commit_msg>Projects sorted ascendingly<commit_after>exports.createProject = function(app, mongoose, request, response, callback) {
	var heading = request.body.heading;
	var description = request.body.description;
	var owner = request.body.owner;
	var users = request.body.users;
	if (owner === '') {
		response.send(false);
		if (callback !== undefined) {
			callback();
		}
		return;
	}
	var outerScope = this;
	this.checkProject(heading, app, mongoose, function(result) {
		if (result.length >= 1) {
			//Project name already exists
			for (var i = result.length - 1; i >= 0; i--) {
				if (result[i].deleted === false) {
					response.send(false);
					if (callback !== undefined) {
						callback();
					}
					return;
				}
			}
		}

		var Project = mongoose.model('Project', app.projectSchema);

		var project = new Project({
			name : heading,
			description : description,
			children : [],
			deleted : false,
			users : users,
			owner : owner
		});
		outerScope.persistProject(project);
		response.send(project);
		if (callback !== undefined) {
			callback();
		}
	});
};

exports.checkProject = function(searchheading, app, mongoose, callback) {
	var res = null;
	var Project = mongoose.model('Project', app.projectSchema);
	Project.find({name: searchheading}, function(err, project) {
		if (err) {
			return console.error(err);
		}
		callback(project);
	});
};

exports.persistProject = function(project) {
	project.save(function(err, data) {
		if (err) {
			console.log(err);
		} else {
			// console.log('Saved : ', data);
		}
	});
};

exports.getAllProjects = function(app, mongoose, request, response, callback) {
	var Project = mongoose.model('Project', app.projectSchema);

	// Project.find({deleted : 'false'}, function(err, projects) {
	// 	if (err) {
	// 		return console.error(err);
	// 	}
	// 	if (callback === undefined) {
	// 		response.send(projects);
	// 	} else {
	// 		response.send(projects);
	// 		callback(projects);
	// 	}

	// });

Project.find({deleted : 'false'}).sort([['name', 'ascending']]).exec(function(err, projects) {
		if (err) {
			return console.error(err);
		}
		if (callback === undefined) {
			response.send(projects);
		} else {
			response.send(projects);
			callback(projects);
		}

	});
};

exports.getProject = function(app, mongoose, request, response, callback) {
	var searchheading = request.body.heading;
	var Project = mongoose.model('Project', app.projectSchema);

	Project.find({name: searchheading}, function(err, project) {
		if (err) {
			return console.error(err);
		}
		if (callback === undefined) {
			response.send(project);
		} else {
			response.send(project);
			callback(project);
		}
	});
};

exports.addChild = function(app, mongoose, request, response, callback) {
	var Project = mongoose.model('Project', app.projectSchema);
	var project = request.body;
	var condition = {_id : project._id};
	var update = project;
	var options = {multi: true};
	Project.update(condition, update, options, function(err, numAffected) {
		console.log(numAffected);
	});
	if (callback === undefined) {
		response.send(project);
	} else {
		response.send(project);
		callback(project);
	}
};

exports.deleteProject = function(app, mongoose, request, response) {
	var Project = mongoose.model('Project', app.projectSchema);
	var project = request.body;
	var condition = {_id : project._id};
	var update = {deleted : true};
	var options = {multi: true};
	Project.update(condition, update, options, function(err, numAffected) {
		console.log(numAffected);
	});
	response.send(true);
};
<|endoftext|>


<commit_before>import Model, {attr, belongsTo} from '@ember-data/model';

export default Model.extend({
    processedAtUTC: attr('moment-utc'),
    deliveredAtUTC: attr('moment-utc'),
    openedAtUTC: attr('moment-utc'),
    failedAtUTC: attr('moment-utc'),
    memberEmail: attr('string'),
    memberName: attr('string'),

    email: belongsTo('email', {embedded: 'always', async: false})
});
<commit_msg>Deleted `email-recipient` model file missed in relationship cleanup<commit_after><|endoftext|>


<commit_before>import Service from '@ember/service';
import {ICON_MAPPING} from 'ghost-admin/components/modal-portal-settings';
import {inject as service} from '@ember/service';
export default class MembersUtilsService extends Service {
    @service config;
    @service settings;

    get isStripeEnabled() {
        const stripeDirect = this.config.get('stripeDirect');

        const hasDirectKeys = !!this.settings.get('stripeSecretKey') && !!this.settings.get('stripePublishableKey');
        const hasConnectKeys = !!this.settings.get('stripeConnectSecretKey') && !!this.settings.get('stripeConnectPublishableKey');

        if (stripeDirect) {
            return hasDirectKeys;
        }

        return hasConnectKeys || hasDirectKeys;
    }

    getPortalPreviewUrl(args) {
        let {
            disableBackground,
            buttonIcon,
            page = 'signup',
            isFree = true,
            isMonthly = true,
            isYearly = true,
            monthlyPrice,
            yearlyPrice,
            currency
        } = args;

        if (!buttonIcon) {
            const defaultIconKeys = ICON_MAPPING.map(icon => icon.value);
            buttonIcon = this.settings.get('portalButtonIcon') || defaultIconKeys[0];
        }

        const baseUrl = this.config.get('blogUrl');
        const portalBase = '/#/portal/preview';
        const settingsParam = new URLSearchParams();
        const signupButtonText = this.settings.get('portalButtonSignupText') || '';

        settingsParam.append('button', this.settings.get('portalButton'));
        settingsParam.append('name', this.settings.get('portalName'));
        settingsParam.append('isFree', isFree);
        settingsParam.append('isMonthly', isMonthly);
        settingsParam.append('isYearly', isYearly);
        settingsParam.append('page', page);
        settingsParam.append('buttonIcon', encodeURIComponent(buttonIcon));
        settingsParam.append('signupButtonText', encodeURIComponent(signupButtonText));

        if (this.settings.get('accentColor') === '' || this.settings.get('accentColor')) {
            settingsParam.append('accentColor', encodeURIComponent(`${this.settings.get('accentColor')}`));
        }
        if (this.settings.get('portalButtonStyle')) {
            settingsParam.append('buttonStyle', encodeURIComponent(this.settings.get('portalButtonStyle')));
        }

        if (monthlyPrice) {
            settingsParam.append('monthlyPrice', monthlyPrice);
        }
        if (yearlyPrice) {
            settingsParam.append('yearlyPrice', yearlyPrice);
        }
        if (currency) {
            settingsParam.append('currency', currency);
        }

        if (disableBackground) {
            settingsParam.append('disableBackground', true);
        }

        return `${baseUrl}${portalBase}?${settingsParam.toString()}`;
    }
}
<commit_msg>Fixed portal plan params in preview mode<commit_after>import Service from '@ember/service';
import {ICON_MAPPING} from 'ghost-admin/components/modal-portal-settings';
import {inject as service} from '@ember/service';
export default class MembersUtilsService extends Service {
    @service config;
    @service settings;

    get isStripeEnabled() {
        const stripeDirect = this.config.get('stripeDirect');

        const hasDirectKeys = !!this.settings.get('stripeSecretKey') && !!this.settings.get('stripePublishableKey');
        const hasConnectKeys = !!this.settings.get('stripeConnectSecretKey') && !!this.settings.get('stripeConnectPublishableKey');

        if (stripeDirect) {
            return hasDirectKeys;
        }

        return hasConnectKeys || hasDirectKeys;
    }

    getPortalPreviewUrl(args) {
        let {
            disableBackground,
            buttonIcon,
            page = 'signup',
            isFreeChecked = true,
            isMonthlyChecked = true,
            isYearlyChecked = true,
            monthlyPrice,
            yearlyPrice,
            currency
        } = args;

        if (!buttonIcon) {
            const defaultIconKeys = ICON_MAPPING.map(icon => icon.value);
            buttonIcon = this.settings.get('portalButtonIcon') || defaultIconKeys[0];
        }

        const baseUrl = this.config.get('blogUrl');
        const portalBase = '/#/portal/preview';
        const settingsParam = new URLSearchParams();
        const signupButtonText = this.settings.get('portalButtonSignupText') || '';

        settingsParam.append('button', this.settings.get('portalButton'));
        settingsParam.append('name', this.settings.get('portalName'));
        settingsParam.append('isFree', isFreeChecked);
        settingsParam.append('isMonthly', isMonthlyChecked);
        settingsParam.append('isYearly', isYearlyChecked);
        settingsParam.append('page', page);
        settingsParam.append('buttonIcon', encodeURIComponent(buttonIcon));
        settingsParam.append('signupButtonText', encodeURIComponent(signupButtonText));

        if (this.settings.get('accentColor') === '' || this.settings.get('accentColor')) {
            settingsParam.append('accentColor', encodeURIComponent(`${this.settings.get('accentColor')}`));
        }
        if (this.settings.get('portalButtonStyle')) {
            settingsParam.append('buttonStyle', encodeURIComponent(this.settings.get('portalButtonStyle')));
        }

        if (monthlyPrice) {
            settingsParam.append('monthlyPrice', monthlyPrice);
        }
        if (yearlyPrice) {
            settingsParam.append('yearlyPrice', yearlyPrice);
        }
        if (currency) {
            settingsParam.append('currency', currency);
        }

        if (disableBackground) {
            settingsParam.append('disableBackground', true);
        }

        return `${baseUrl}${portalBase}?${settingsParam.toString()}`;
    }
}
<|endoftext|>


<commit_before>  'use strict';

  module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({
      // Metadata.
      pkg: grunt.file.readJSON('package.json'),
      banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
        ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
      /*emberTemplates: {
        build: {
          files: {
          }
        },
      },*/
      uglify: {
        build: {
          options: {
            sourceMap: true,
            sourceMapIncludeSources: true,
          },
          files: {
            'assets/vendor/js/libs.min.js': [
              'bower_components/jquery/dist/jquery.js',
              'bower_components/handlebars/handlebars.js',
              'bower_components/ember/ember.js',
              'bower_components/ember-data/ember-data.js',
              'bower_components/moment/moment.js',
              'bower_components/bootstrap/dist/js/bootstrap.js',
            ],
          }
        },
      },
      less: {
        build: {
          files: {
            'assets/vendor/css/libs.min.css': [
              'bower_components/bootstrap/less/bootstrap.less',
              'bower_components/fontawesome/less/font-awesome.less'
            ]
          }
        }
      },
      copy: {
        build: {
          files: [
            {expand: true, cwd: 'bower_components/bootstrap/dist/fonts/', src: ['**'],
            dest: 'assets/vendor/fonts/'},
            {expand: true, cwd: 'bower_components/fontawesome/fonts/', src: ['**'],
            dest: 'assets/vendor/fonts/'},
          ]
        }
      }
    });

    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-ember-templates');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-copy');

    // Default task.
    grunt.registerTask('default', ['uglify', 'less', 'copy']);
  };
<commit_msg>fix gruntfile<commit_after>  'use strict';

  module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({
      // Metadata.
      pkg: grunt.file.readJSON('package.json'),
      banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
        ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
      /*emberTemplates: {
        build: {
          files: {
          }
        },
      },*/
      uglify: {
        build: {
          options: {
            sourceMap: true,
            sourceMapIncludeSources: true,
          },
          files: {
            'assets/vendor/js/libs.min.js': [
              'bower_components/jquery/jquery.js',
              'bower_components/handlebars/handlebars.js',
              'bower_components/ember/ember.js',
              'bower_components/ember-data/ember-data.js',
              'bower_components/moment/moment.js',
              'bower_components/bootstrap/dist/js/bootstrap.js',
            ],
          }
        },
      },
      less: {
        build: {
          files: {
            'assets/vendor/css/libs.min.css': [
              'bower_components/bootstrap/less/bootstrap.less',
              'bower_components/fontawesome/less/font-awesome.less'
            ]
          }
        }
      },
      copy: {
        build: {
          files: [
            {expand: true, cwd: 'bower_components/bootstrap/dist/fonts/', src: ['**'],
            dest: 'assets/vendor/fonts/'},
            {expand: true, cwd: 'bower_components/fontawesome/fonts/', src: ['**'],
            dest: 'assets/vendor/fonts/'},
          ]
        }
      }
    });

    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-ember-templates');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-copy');

    // Default task.
    grunt.registerTask('default', ['uglify', 'less', 'copy']);
  };
<|endoftext|>


<commit_before>var map;
var hasInit = false;
var markersArray = [];

google.maps.event.addDomListener(window, 'load', initialize);

//Generate map during initial map load
function initialize() {
  if (!hasInit) {
    var mapOptions = {
      center: new google.maps.LatLng(40.714623,-74.006605 ),
      zoom: 12,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    map = new google.maps.Map(document.getElementById("map-canvas"),
      mapOptions);

    hasInit = true;
  }

  // Create the DIV to hold the control and call the ArticleControl() constructor
  // passing in this DIV.
  var articleControlDiv = document.createElement('div');
  var articleControl = new ArticleControl(articleControlDiv, map);

  articleControlDiv.index = 1;
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(articleControlDiv);
}

//The load article control will load article markers onto the map
function ArticleControl(controlDiv, map) {
  // Set CSS styles for the DIV containing the control
  // Setting padding to 5 px will offset the control
  // from the edge of the map.
  controlDiv.style.padding = '5px';

  // Set CSS for the control border.
  var controlUI = document.createElement('div');
  controlUI.style.backgroundColor = 'white';
  controlUI.style.borderStyle = 'solid';
  controlUI.style.borderWidth = '2px';
  controlUI.style.cursor = 'pointer';
  controlUI.style.textAlign = 'center';
  controlUI.title = 'Load articles when you click the button';
  controlDiv.appendChild(controlUI);

  // Set CSS for the control interior.
  var controlText = document.createElement('div');
  controlText.style.fontFamily = 'Arial,sans-serif';
  controlText.style.fontSize = '12px';
  controlText.style.paddingLeft = '4px';
  controlText.style.paddingRight = '4px';
  controlText.innerHTML = 'Load Articles';
  controlUI.appendChild(controlText);

  // Setup the click event listeners: simply set the map to Chicago.
  google.maps.event.addDomListener(controlUI, 'click', loadArticles);
}

// Adds marker to specfic lat lng
function addMarker(JSONObj) {
	var myLatLng = (JSONObj.fields.lat && JSONObj.fields.lon) ? new google.maps.LatLng(JSONObj.fields.lat, JSONObj.fields.lon) : null;
  if (myLatLng == null) {
    console.log("Lat Lng for article was null. No marker made");
    return;
  }
	var marker = new google.maps.Marker({
	  position: myLatLng,
	  map: map,
	  title: JSONObj.headline,
          url: JSONObj.fields.url
	});

  markersArray.push(marker);

  var infowindow = new google.maps.InfoWindow({
      content: JSONObj.fields.blurb
  });

  google.maps.event.addListener(marker, 'mouseover', function() {
    infowindow.open(map,marker);
  });
  google.maps.event.addListener(marker, 'mouseout', function() {
    infowindow.close();
  });
  google.maps.event.addListener(marker, 'click', function() {
    window.open(this.url);
  });
  console.log("Plotting headline " + JSONObj.fields.headline + "at " + JSONObj.fields.lat + " " + JSONObj.fields.lon);
  console.log("Plotting headline " + JSONObj.headline + "at " + JSONObj.lat + " " + JSONObj.lng);
}

// Passes in lat lng from center of map and returns relevant articles. We then build markers on the map.
function loadArticles() {
  //clear map markers
  clearMarkers();

  //Get lat lng for center
  var currentLatLng = map.getCenter();
  var lat = currentLatLng.lat();
  var lng = currentLatLng.lng();

  //Get region radius
  var bounds = map.getBounds();
  var swPoint = bounds.getSouthWest();
  var xOffset = Math.abs(swPoint.lng() - lng);
  var yOffset = Math.abs(swPoint.lat() - lat);

  //Retreive list of locations and stories from server
  var JSONArr = getFromServer(lat, lng, xOffset, yOffset);
  var JSONArrObj = JSON.parse(JSONArr);

  //loop through relevant articles and get address
  for(var i = 0; i < JSONArrObj.length; i++) {
    addMarker(JSONArrObj[i]);
  }
}

function clearMarkers() {
  for (var i = 0; i < markersArray.length; i++) {
    markersArray[i].setMap(null);
  }
}

function getFromServer(lat, lng, xOffset, yOffset) {
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();
    console.log("getting from " + "/maploco/stories?lat=" + lat + "&long=" + lng + "&xoffset=" + xOffset + "&yoffset=" + yOffset);
    xmlHttp.open( "GET", "/maploco/stories?lat=" + lat + "&long=" + lng + "&xoffset=" + xOffset + "&yoffset=" + yOffset, false);
    xmlHttp.send();
    return xmlHttp.responseText;
}
<commit_msg>Added createRequest method to accomodate different types of browsers.<commit_after>var map;
var request;
var hasInit = false;
var markersArray = [];

google.maps.event.addDomListener(window, 'load', initialize);

//Generate map during initial map load
function initialize() {
  if (!hasInit) {
    var mapOptions = {
      center: new google.maps.LatLng(40.714623,-74.006605 ),
      zoom: 12,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    map = new google.maps.Map(document.getElementById("map-canvas"),
      mapOptions);

    hasInit = true;
  }

  // Create the DIV to hold the control and call the ArticleControl() constructor
  // passing in this DIV.
  var articleControlDiv = document.createElement('div');
  var articleControl = new ArticleControl(articleControlDiv, map);

  articleControlDiv.index = 1;
  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(articleControlDiv);
}

//The load article control will load article markers onto the map
function ArticleControl(controlDiv, map) {
  // Set CSS styles for the DIV containing the control
  // Setting padding to 5 px will offset the control
  // from the edge of the map.
  controlDiv.style.padding = '5px';

  // Set CSS for the control border.
  var controlUI = document.createElement('div');
  controlUI.style.backgroundColor = 'white';
  controlUI.style.borderStyle = 'solid';
  controlUI.style.borderWidth = '2px';
  controlUI.style.cursor = 'pointer';
  controlUI.style.textAlign = 'center';
  controlUI.title = 'Load articles when you click the button';
  controlDiv.appendChild(controlUI);

  // Set CSS for the control interior.
  var controlText = document.createElement('div');
  controlText.style.fontFamily = 'Arial,sans-serif';
  controlText.style.fontSize = '12px';
  controlText.style.paddingLeft = '4px';
  controlText.style.paddingRight = '4px';
  controlText.innerHTML = 'Load Articles';
  controlUI.appendChild(controlText);

  // Setup the click event listeners: simply set the map to Chicago.
  google.maps.event.addDomListener(controlUI, 'click', loadArticles);
}

// Adds marker to specfic lat lng
function addMarker(JSONObj) {
	var myLatLng = (JSONObj.fields.lat && JSONObj.fields.lon) ? new google.maps.LatLng(JSONObj.fields.lat, JSONObj.fields.lon) : null;
  if (myLatLng == null) {
    console.log("Lat Lng for article was null. No marker made");
    return;
  }
	var marker = new google.maps.Marker({
	  position: myLatLng,
	  map: map,
	  title: JSONObj.headline,
          url: JSONObj.fields.url
	});

  markersArray.push(marker);

  var infowindow = new google.maps.InfoWindow({
      content: JSONObj.fields.blurb
  });

  google.maps.event.addListener(marker, 'mouseover', function() {
    infowindow.open(map,marker);
  });
  google.maps.event.addListener(marker, 'mouseout', function() {
    infowindow.close();
  });
  google.maps.event.addListener(marker, 'click', function() {
    window.open(this.url);
  });
  console.log("Plotting headline " + JSONObj.fields.headline + "at " + JSONObj.fields.lat + " " + JSONObj.fields.lon);
  console.log("Plotting headline " + JSONObj.headline + "at " + JSONObj.lat + " " + JSONObj.lng);
}

// Passes in lat lng from center of map and returns relevant articles. We then build markers on the map.
function loadArticles() {
  //clear map markers
  clearMarkers();

  //Get lat lng for center
  var currentLatLng = map.getCenter();
  var lat = currentLatLng.lat();
  var lng = currentLatLng.lng();

  //Get region radius
  var bounds = map.getBounds();
  var swPoint = bounds.getSouthWest();
  var xOffset = Math.abs(swPoint.lng() - lng);
  var yOffset = Math.abs(swPoint.lat() - lat);

  //Retreive list of locations and stories from server
  var JSONArr = getFromServer(lat, lng, xOffset, yOffset);
  var JSONArrObj = JSON.parse(JSONArr);

  //loop through relevant articles and get address
  for(var i = 0; i < JSONArrObj.length; i++) {
    addMarker(JSONArrObj[i]);
  }
}

function clearMarkers() {
  for (var i = 0; i < markersArray.length; i++) {
    markersArray[i].setMap(null);
  }
}

function getFromServer(lat, lng, xOffset, yOffset) {
    var url = "/maploco/stories?lat=" + lat + "&long=" + lng + "&xoffset=" + xOffset + "&yoffset=" + yOffset;
    console.log("getting from " + url);
    createRequest();
    request.open("GET", url, false);
    request.send(null);
    return request.responseText; // Will update this to be asynchronous
}

// Creates request based on browser used by user
function createRequest() {
  try {
    request = new XMLHttpRequest();
  } catch (trymicrosoft) {
    try {
      request = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (othermicrosoft) {
      try {
        request = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (failed) {
        request = null;
      }
    }
  }
  if (request == null) {
    alert("Error creating XMLHttpRequest. Try switching browsers");
  }
}
<|endoftext|>


<commit_before>/* eslint-disable ghost/ember/alias-model-in-controller */
import $ from 'jquery';
import Controller from '@ember/controller';
import NavigationItem from 'ghost-admin/models/navigation-item';
import RSVP from 'rsvp';
import {computed} from '@ember/object';
import {isEmpty} from '@ember/utils';
import {isThemeValidationError} from 'ghost-admin/services/ajax';
import {notEmpty} from '@ember/object/computed';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';

export default Controller.extend({
    config: service(),
    ghostPaths: service(),
    notifications: service(),
    session: service(),
    settings: service(),

    newNavItem: null,

    dirtyAttributes: false,

    themes: null,
    themeToDelete: null,
    init() {
        this._super(...arguments);
        this.set('newNavItem', NavigationItem.create({isNew: true}));
    },

    showDeleteThemeModal: notEmpty('themeToDelete'),

    blogUrl: computed('config.blogUrl', function () {
        let url = this.get('config.blogUrl');

        return url.slice(-1) !== '/' ? `${url}/` : url;
    }),

    actions: {
        save() {
            this.get('save').perform();
        },

        addNavItem() {
            let newNavItem = this.get('newNavItem');

            // If the url sent through is blank (user never edited the url)
            if (newNavItem.get('url') === '') {
                newNavItem.set('url', '/');
            }

            return newNavItem.validate().then(() => {
                this.addNewNavItem();
            });
        },

        deleteNavItem(item) {
            if (!item) {
                return;
            }

            let navItems = this.get('settings.navigation');

            navItems.removeObject(item);
            this.set('dirtyAttributes', true);
        },

        updateLabel(label, navItem) {
            if (!navItem) {
                return;
            }

            navItem.set('label', label);
            this.set('dirtyAttributes', true);
        },

        updateUrl(url, navItem) {
            if (!navItem) {
                return;
            }

            navItem.set('url', url);
            this.set('dirtyAttributes', true);
        },

        toggleLeaveSettingsModal(transition) {
            let leaveTransition = this.get('leaveSettingsTransition');

            if (!transition && this.get('showLeaveSettingsModal')) {
                this.set('leaveSettingsTransition', null);
                this.set('showLeaveSettingsModal', false);
                return;
            }

            if (!leaveTransition || transition.targetName === leaveTransition.targetName) {
                this.set('leaveSettingsTransition', transition);

                // if a save is running, wait for it to finish then transition
                if (this.get('save.isRunning')) {
                    return this.get('save.last').then(() => {
                        transition.retry();
                    });
                }

                // we genuinely have unsaved data, show the modal
                this.set('showLeaveSettingsModal', true);
            }
        },

        leaveSettings() {
            let transition = this.get('leaveSettingsTransition');
            let settings = this.get('settings');

            if (!transition) {
                this.get('notifications').showAlert('Sorry, there was an error in the application. Please let the Ghost team know what happened.', {type: 'error'});
                return;
            }

            // roll back changes on settings props
            settings.rollbackAttributes();
            this.set('dirtyAttributes', false);

            return transition.retry();
        },

        activateTheme(theme) {
            return theme.activate().then((theme) => {
                let themeName = theme.get('name');

                if (!isEmpty(theme.get('warnings'))) {
                    this.set('themeWarnings', theme.get('warnings'));
                    this.set('showThemeWarningsModal', true);
                }

                if (!isEmpty(theme.get('errors'))) {
                    this.set('themeErrors', theme.get('errors'));
                    this.set('showThemeWarningsModal', true);
                }

                if (this.get('themeErrors') || this.get('themeWarnings')) {
                    let message = `${themeName} activated successfully but some warnings/errors were detected.
                                   You are still able to use and activate the theme. Here is your report...`;
                    this.set('message', message);
                }
            }).catch((error) => {
                if (isThemeValidationError(error)) {
                    let errors = error.payload.errors[0].errorDetails;
                    let fatalErrors = [];
                    let normalErrors = [];

                    // to have a proper grouping of fatal errors and none fatal, we need to check
                    // our errors for the fatal property
                    if (errors.length > 0) {
                        for (let i = 0; i < errors.length; i += 1) {
                            if (errors[i].fatal) {
                                fatalErrors.push(errors[i]);
                            } else {
                                normalErrors.push(errors[i]);
                            }
                        }
                    }

                    this.set('themeErrors', normalErrors);
                    this.set('themeFatalErrors', fatalErrors);
                    this.set('showThemeErrorsModal', true);
                    return;
                }

                throw error;
            });
        },

        downloadTheme(theme) {
            let downloadURL = `${this.get('ghostPaths.apiRoot')}/themes/${theme.name}`;
            let iframe = $('#iframeDownload');

            if (iframe.length === 0) {
                iframe = $('<iframe>', {id: 'iframeDownload'}).hide().appendTo('body');
            }

            iframe.attr('src', downloadURL);
        },

        deleteTheme(theme) {
            if (theme) {
                return this.set('themeToDelete', theme);
            }

            return this._deleteTheme();
        },

        hideDeleteThemeModal() {
            this.set('themeToDelete', null);
        },

        hideThemeWarningsModal() {
            this.set('themeWarnings', null);
            this.set('themeErrors', null);
            this.set('themeFatalErrors', null);
            this.set('showThemeWarningsModal', false);
            this.set('showThemeErrorsModal', false);
        },

        reset() {
            this.set('newNavItem', NavigationItem.create({isNew: true}));
        }
    },

    save: task(function* () {
        let navItems = this.get('settings.navigation');
        let newNavItem = this.get('newNavItem');
        let notifications = this.get('notifications');
        let validationPromises = [];

        if (!newNavItem.get('isBlank')) {
            validationPromises.pushObject(this.send('addNavItem'));
        }

        navItems.map((item) => {
            validationPromises.pushObject(item.validate());
        });

        try {
            yield RSVP.all(validationPromises);
            this.set('dirtyAttributes', false);
            return yield this.get('settings').save();
        } catch (error) {
            if (error) {
                notifications.showAPIError(error);
                throw error;
            }
        }
    }),

    addNewNavItem() {
        let navItems = this.get('settings.navigation');
        let newNavItem = this.get('newNavItem');

        newNavItem.set('isNew', false);
        navItems.pushObject(newNavItem);
        this.set('dirtyAttributes', true);
        this.set('newNavItem', NavigationItem.create({isNew: true}));
        $('.gh-blognav-line:last input:first').focus();
    },

    _deleteTheme() {
        let theme = this.get('store').peekRecord('theme', this.get('themeToDelete').name);

        if (!theme) {
            return;
        }

        return theme.destroyRecord().then(() => {
            // HACK: this is a private method, we need to unload from the store
            // here so that uploading another theme with the same "id" doesn't
            // attempt to update the deleted record
            theme.unloadRecord();
        }).catch((error) => {
            this.get('notifications').showAPIError(error);
        });
    }
});
<commit_msg>🐛 Fixed theme download links (#1053)<commit_after>/* eslint-disable ghost/ember/alias-model-in-controller */
import $ from 'jquery';
import Controller from '@ember/controller';
import NavigationItem from 'ghost-admin/models/navigation-item';
import RSVP from 'rsvp';
import {computed} from '@ember/object';
import {isEmpty} from '@ember/utils';
import {isThemeValidationError} from 'ghost-admin/services/ajax';
import {notEmpty} from '@ember/object/computed';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';

export default Controller.extend({
    config: service(),
    ghostPaths: service(),
    notifications: service(),
    session: service(),
    settings: service(),

    newNavItem: null,

    dirtyAttributes: false,

    themes: null,
    themeToDelete: null,
    init() {
        this._super(...arguments);
        this.set('newNavItem', NavigationItem.create({isNew: true}));
    },

    showDeleteThemeModal: notEmpty('themeToDelete'),

    blogUrl: computed('config.blogUrl', function () {
        let url = this.get('config.blogUrl');

        return url.slice(-1) !== '/' ? `${url}/` : url;
    }),

    actions: {
        save() {
            this.get('save').perform();
        },

        addNavItem() {
            let newNavItem = this.get('newNavItem');

            // If the url sent through is blank (user never edited the url)
            if (newNavItem.get('url') === '') {
                newNavItem.set('url', '/');
            }

            return newNavItem.validate().then(() => {
                this.addNewNavItem();
            });
        },

        deleteNavItem(item) {
            if (!item) {
                return;
            }

            let navItems = this.get('settings.navigation');

            navItems.removeObject(item);
            this.set('dirtyAttributes', true);
        },

        updateLabel(label, navItem) {
            if (!navItem) {
                return;
            }

            navItem.set('label', label);
            this.set('dirtyAttributes', true);
        },

        updateUrl(url, navItem) {
            if (!navItem) {
                return;
            }

            navItem.set('url', url);
            this.set('dirtyAttributes', true);
        },

        toggleLeaveSettingsModal(transition) {
            let leaveTransition = this.get('leaveSettingsTransition');

            if (!transition && this.get('showLeaveSettingsModal')) {
                this.set('leaveSettingsTransition', null);
                this.set('showLeaveSettingsModal', false);
                return;
            }

            if (!leaveTransition || transition.targetName === leaveTransition.targetName) {
                this.set('leaveSettingsTransition', transition);

                // if a save is running, wait for it to finish then transition
                if (this.get('save.isRunning')) {
                    return this.get('save.last').then(() => {
                        transition.retry();
                    });
                }

                // we genuinely have unsaved data, show the modal
                this.set('showLeaveSettingsModal', true);
            }
        },

        leaveSettings() {
            let transition = this.get('leaveSettingsTransition');
            let settings = this.get('settings');

            if (!transition) {
                this.get('notifications').showAlert('Sorry, there was an error in the application. Please let the Ghost team know what happened.', {type: 'error'});
                return;
            }

            // roll back changes on settings props
            settings.rollbackAttributes();
            this.set('dirtyAttributes', false);

            return transition.retry();
        },

        activateTheme(theme) {
            return theme.activate().then((theme) => {
                let themeName = theme.get('name');

                if (!isEmpty(theme.get('warnings'))) {
                    this.set('themeWarnings', theme.get('warnings'));
                    this.set('showThemeWarningsModal', true);
                }

                if (!isEmpty(theme.get('errors'))) {
                    this.set('themeErrors', theme.get('errors'));
                    this.set('showThemeWarningsModal', true);
                }

                if (this.get('themeErrors') || this.get('themeWarnings')) {
                    let message = `${themeName} activated successfully but some warnings/errors were detected.
                                   You are still able to use and activate the theme. Here is your report...`;
                    this.set('message', message);
                }
            }).catch((error) => {
                if (isThemeValidationError(error)) {
                    let errors = error.payload.errors[0].errorDetails;
                    let fatalErrors = [];
                    let normalErrors = [];

                    // to have a proper grouping of fatal errors and none fatal, we need to check
                    // our errors for the fatal property
                    if (errors.length > 0) {
                        for (let i = 0; i < errors.length; i += 1) {
                            if (errors[i].fatal) {
                                fatalErrors.push(errors[i]);
                            } else {
                                normalErrors.push(errors[i]);
                            }
                        }
                    }

                    this.set('themeErrors', normalErrors);
                    this.set('themeFatalErrors', fatalErrors);
                    this.set('showThemeErrorsModal', true);
                    return;
                }

                throw error;
            });
        },

        downloadTheme(theme) {
            let downloadURL = `${this.get('ghostPaths.apiRoot')}/themes/${theme.name}/download/`;
            let iframe = $('#iframeDownload');

            if (iframe.length === 0) {
                iframe = $('<iframe>', {id: 'iframeDownload'}).hide().appendTo('body');
            }

            iframe.attr('src', downloadURL);
        },

        deleteTheme(theme) {
            if (theme) {
                return this.set('themeToDelete', theme);
            }

            return this._deleteTheme();
        },

        hideDeleteThemeModal() {
            this.set('themeToDelete', null);
        },

        hideThemeWarningsModal() {
            this.set('themeWarnings', null);
            this.set('themeErrors', null);
            this.set('themeFatalErrors', null);
            this.set('showThemeWarningsModal', false);
            this.set('showThemeErrorsModal', false);
        },

        reset() {
            this.set('newNavItem', NavigationItem.create({isNew: true}));
        }
    },

    save: task(function* () {
        let navItems = this.get('settings.navigation');
        let newNavItem = this.get('newNavItem');
        let notifications = this.get('notifications');
        let validationPromises = [];

        if (!newNavItem.get('isBlank')) {
            validationPromises.pushObject(this.send('addNavItem'));
        }

        navItems.map((item) => {
            validationPromises.pushObject(item.validate());
        });

        try {
            yield RSVP.all(validationPromises);
            this.set('dirtyAttributes', false);
            return yield this.get('settings').save();
        } catch (error) {
            if (error) {
                notifications.showAPIError(error);
                throw error;
            }
        }
    }),

    addNewNavItem() {
        let navItems = this.get('settings.navigation');
        let newNavItem = this.get('newNavItem');

        newNavItem.set('isNew', false);
        navItems.pushObject(newNavItem);
        this.set('dirtyAttributes', true);
        this.set('newNavItem', NavigationItem.create({isNew: true}));
        $('.gh-blognav-line:last input:first').focus();
    },

    _deleteTheme() {
        let theme = this.get('store').peekRecord('theme', this.get('themeToDelete').name);

        if (!theme) {
            return;
        }

        return theme.destroyRecord().then(() => {
            // HACK: this is a private method, we need to unload from the store
            // here so that uploading another theme with the same "id" doesn't
            // attempt to update the deleted record
            theme.unloadRecord();
        }).catch((error) => {
            this.get('notifications').showAPIError(error);
        });
    }
});
<|endoftext|>


<commit_before>import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
import {action} from '@ember/object';
import {inject as service} from '@ember/service';

export default class IndexRoute extends AuthenticatedRoute {
    @service infinity;
    @service session;

    beforeModel() {
        super.beforeModel(...arguments);

        const user = this.session.user;

        if (user.isAuthorOrContributor) {
            return this.transitionTo('settings.staff.user', user);
        }
    }

    model() {
        return this.session.user;
    }

    setupController(controller) {
        super.setupController(...arguments);
        controller.backgroundUpdateTask.perform();
    }

    buildRouteInfoMetadata() {
        return {
            titleToken: 'Staff'
        };
    }
}
<commit_msg>Fixed linter error<commit_after>import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
import {inject as service} from '@ember/service';

export default class IndexRoute extends AuthenticatedRoute {
    @service infinity;
    @service session;

    beforeModel() {
        super.beforeModel(...arguments);

        const user = this.session.user;

        if (user.isAuthorOrContributor) {
            return this.transitionTo('settings.staff.user', user);
        }
    }

    model() {
        return this.session.user;
    }

    setupController(controller) {
        super.setupController(...arguments);
        controller.backgroundUpdateTask.perform();
    }

    buildRouteInfoMetadata() {
        return {
            titleToken: 'Staff'
        };
    }
}
<|endoftext|>


<commit_before>/*
 * grunt-aws-setup
 * https://github.com/TeamPraxis/grunt-aws-setup
 *
 * Copyright (c) 2014 Keith Hamasaki
 * Licensed under the MIT license.
 */

/*jshint node: true */
'use strict';

var AWS = require('aws-sdk'),
    async = require('async'),
    _ = require('lodash');

_.str = require('underscore.string');
_.mixin(_.str.exports());

module.exports = function(grunt) {

  grunt.registerMultiTask('aws_cloudformation', 'Execute a CloudFormation stack.', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      region: 'us-west-1',
      configVariable: this.nameArgs
    });

    // check for required options
    if (!options.stackName) {
      grunt.log.error('stackName must be defined.');
      return;
    }

    if (!options.definitionFile) {
      grunt.log.error('definitionFile must be defined.');
      return;
    }

    if (!grunt.file.isFile(options.definitionFile)) {
      grunt.log.error('Could not find definitionFile.');
      return;
    }

    var done = this.async();
    var cf = new AWS.CloudFormation({ region: options.region });
    var noUpdateFlag = false;

    async.waterfall([
      // check to see if the stack exists and create or update it
      _.bind(cf.describeStacks, cf, { }),
      function (data, callback) {
        var stack = _.findWhere(data.Stacks, { StackName: options.stackName });
        var params = {
          StackName: options.stackName,
          TemplateBody: grunt.file.read(options.definitionFile)
        };
        if (options.capabilities) {
          params.Capabilities = options.capabilities;
        }
        if (options.params) {
          params.Parameters = _.chain(options.params)
            .pairs()
            .map(function (val) {
              return {
                ParameterKey: val[0],
                ParameterValue: val[1]
              };
            })
            .value();
        }
        if (stack) {
          grunt.log.writeln('Updating CloudFormation stack: ' + options.stackName);
          cf.updateStack(params, function (err, data) {
            // ignore errors about no updates
            if (err && err.message === 'No updates are to be performed.') {
              grunt.log.writeln('No updates required, retrieving current outputs.');
              callback(null, 'NO_UPDATES');
              return;
            }
            callback(err, data);
          });
        } else {
          grunt.log.writeln('Creating CloudFormation stack: ' + options.stackName);
          cf.createStack(params, callback);
        }
      },
      // wait until it is complete
      function (data, callback) {
        noUpdateFlag = (data === 'NO_UPDATES');
        var status, reason, outputs;
        grunt.log.write('Waiting ');
        async.doUntil(function (callback) {
          grunt.log.write('.');
          cf.describeStacks({ StackName: options.stackName }, function (err, data) {
            if (err) {
              callback(err);
              return;
            }
            status = data.Stacks[0].StackStatus;
            reason = data.Stacks[0].StackStatusReason;
            outputs = data.Stacks[0].Outputs;

            setTimeout(callback, noUpdateFlag ? 1 : 5000);
          });
        }, function () {
          return _.endsWith(status, 'COMPLETE') || _.endsWith(status, 'FAILED');
        }, function (err) {
          grunt.log.writeln();
          callback(err, status, reason, outputs);
        });
      }
    ], function (err, status, reason, outputs) {
      if (err) {
        grunt.log.error('An error occurred: ' + JSON.stringify(err, null, 2));
        done(false);
        return;
      }
      // if no updates were made, ignore the status
      if (noUpdateFlag) {
        status = 'NO_UPDATE';
      }
      switch (status) {
        case 'CREATE_FAILED':
        case 'UPDATE_ROLLBACK_FAILED':
        case 'UPDATE_ROLLBACK_COMPLETE':
        case 'ROLLBACK_COMPLETE':
          grunt.log.error('CloudFormation Failed.');
          grunt.log.error('Status: ' + status);
          if (reason) {
            grunt.log.error('Reason: ' + reason);
          }
          done(false);
          break;
        default:
          grunt.log.writeln('CloudFormation Complete.');
          grunt.log.writeln('Status: ' + status);
          if (reason) {
            grunt.log.writeln('Reason: ' + reason);
          }
          var configOutput = {};
          _.each(outputs, function (output) {
            configOutput[output.OutputKey] = output.OutputValue;
          });
          grunt.config.set(options.configVariable, configOutput);
          done();
        }
    });
  });
};
<commit_msg>Output events rather than '.' and list the output variables at then end.<commit_after>/*
 * grunt-aws-setup
 * https://github.com/TeamPraxis/grunt-aws-setup
 *
 * Copyright (c) 2014 Keith Hamasaki
 * Licensed under the MIT license.
 */

/*jshint node: true */
'use strict';

var AWS = require('aws-sdk'),
    async = require('async'),
    _ = require('lodash');

_.str = require('underscore.string');
_.mixin(_.str.exports());

module.exports = function(grunt) {

  grunt.registerMultiTask('aws_cloudformation', 'Execute a CloudFormation stack.', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      region: 'us-west-1',
      configVariable: this.nameArgs
    });

    // check for required options
    if (!options.stackName) {
      grunt.log.error('stackName must be defined.');
      return;
    }

    if (!options.definitionFile) {
      grunt.log.error('definitionFile must be defined.');
      return;
    }

    if (!grunt.file.isFile(options.definitionFile)) {
      grunt.log.error('Could not find definitionFile.');
      return;
    }

    var done = this.async();
    var cf = new AWS.CloudFormation({ region: options.region });
    var noUpdateFlag = false;

    async.waterfall([
      // check to see if the stack exists and create or update it
      _.bind(cf.describeStacks, cf, { }),
      function (data, callback) {
        var stack = _.findWhere(data.Stacks, { StackName: options.stackName });
        var params = {
          StackName: options.stackName,
          TemplateBody: grunt.file.read(options.definitionFile)
        };
        if (options.capabilities) {
          params.Capabilities = options.capabilities;
        }
        if (options.params) {
          params.Parameters = _.chain(options.params)
            .pairs()
            .map(function (val) {
              return {
                ParameterKey: val[0],
                ParameterValue: val[1]
              };
            })
            .value();
        }
        if (stack) {
          grunt.log.writeln('Updating CloudFormation stack: ' + options.stackName);
          cf.updateStack(params, function (err, data) {
            // ignore errors about no updates
            if (err && err.message === 'No updates are to be performed.') {
              grunt.log.writeln('No updates required, retrieving current outputs.');
              callback(null, 'NO_UPDATES');
              return;
            }
            callback(err, data);
          });
        } else {
          grunt.log.writeln('Creating CloudFormation stack: ' + options.stackName);
          cf.createStack(params, callback);
        }
      },
      // wait until it is complete
      function (data, callback) {
        noUpdateFlag = (data === 'NO_UPDATES');
        var status, reason, outputs;
        var events = [];
        grunt.log.writeln('Starting...');
        async.doUntil(function (callback) {
          cf.describeStackEvents({ StackName: options.stackName }, function (err, data) {
            if (err) {
              grunt.log.writeln('Error:', err);
            }
            // Ignore errors
            if (data && data.StackEvents) {
              var newEvents = _.difference(_.pluck(data.StackEvents, 'EventId'), _.pluck(events, 'EventId'));
              _.forEach(newEvents, function (item) {
                var newEvent = _.find(data.StackEvents, {'EventId': item});
                events.push(newEvent);
                grunt.log.writeln(newEvent.ResourceType, ' - ', newEvent.LogicalResourceId, ' - ', newEvent.ResourceStatus);
              });
            }
            cf.describeStacks({ StackName: options.stackName }, function (err, data) {
              if (err) {
                callback(err);
                return;
              }
              status = data.Stacks[0].StackStatus;
              reason = data.Stacks[0].StackStatusReason;
              outputs = data.Stacks[0].Outputs;

              setTimeout(callback, noUpdateFlag ? 1 : 5000);
            });
          });
        }, function () {
          return _.endsWith(status, 'COMPLETE') || _.endsWith(status, 'FAILED');
        }, function (err) {
          grunt.log.writeln();
          callback(err, status, reason, outputs);
        });
      }
    ], function (err, status, reason, outputs) {
      if (err) {
        grunt.log.error('An error occurred: ' + JSON.stringify(err, null, 2));
        done(false);
        return;
      }
      // if no updates were made, ignore the status
      if (noUpdateFlag) {
        status = 'NO_UPDATE';
      }
      switch (status) {
        case 'CREATE_FAILED':
        case 'UPDATE_ROLLBACK_FAILED':
        case 'UPDATE_ROLLBACK_COMPLETE':
        case 'ROLLBACK_COMPLETE':
          grunt.log.error('CloudFormation Failed.');
          grunt.log.error('Status: ' + status);
          if (reason) {
            grunt.log.error('Reason: ' + reason);
          }
          done(false);
          break;
        default:
          grunt.log.writeln('CloudFormation Complete.');
          grunt.log.writeln('Status: ' + status);
          if (reason) {
            grunt.log.writeln('Reason: ' + reason);
          }
          var configOutput = {};
          grunt.log.writeln(' Outputs');
          grunt.log.writeln('---------');
          _.each(outputs, function (output) {
            grunt.log.writeln(output.OutputKey + ' = ' + output.OutputValue);
            configOutput[output.OutputKey] = output.OutputValue;
          });
          grunt.config.set(options.configVariable, configOutput);
          done();
        }
    });
  });
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Torn City automatic Gym and Crime bot
// @namespace    http://liquidpineapple.net
// @version      0.5
// @description  Try to take over the world, for the lazy.
// @author       Jurriaan Den Toonder<jurriaan.toonder@liquidpineapple.net>
// @downloadURL  https://github.com/Fastjur/Torn-City-Bot/raw/master/src/TornCityBot.user.js
// @updateURL    https://github.com/Fastjur/Torn-City-Bot/raw/master/src/TornCityBot.user.js
// @match        http://www.torn.com/*
// @require      http://code.jquery.com/jquery-2.2.2.min.js
// @run-at       document-end
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// ==/UserScript==
'use strict';

$(document).ready(function(){
    console.log("Torn city bot loaded!");
    window.setInterval(init, 2000);
});

function init() {
    var action = GM_getValue('action', 'gym');
    var stats = checkStats();
    if (action === 'gym') {
        GM_setValue('action', 'gym');
        if (stats['energy'] >= 5) {
            console.log("Energy >= 5, doGym()");
            var gymStep = GM_getValue('gym_step', 1);
            doGym(gymStep);
        } else {
            GM_setValue('action', 'crime');
        }
    } else if (action === 'crime') {
        if (stats['nerve'] >= 4) {
            console.log("Nerve >= 4, doCrime()");
            var crimeStep = GM_getValue('crime_step', 1);
            console.log("CRIME STEP: " + crimeStep);
            doCrime(crimeStep);
        } else {
            GM_deleteValue('action');//Cannot do anything
        }
    } else {
        console.error("Invalid action, resetting bot and reloading");
        GM_deleteValue('action');
        window.location.href = '/index.php';
    }
}

function checkStats() {
    var Energy = document.getElementById('energy').children[1].dataset.current;
    var Nerve = document.getElementById('nerve').children[1].dataset.current;
    var Happy = document.getElementById('happy').children[1].dataset.current;
    var Life = document.getElementById('life').children[1].dataset.current;
    return {
        'energy': Energy,
        'nerve': Nerve,
        'happy': Happy,
        'life': Life
    };
}

function doGym(step) {
    if (step === 1) {
        console.log("doGym step 1");
        GM_setValue('gym_step', 2);
        if (window.location.pathname == '/gym.php'){
            doGym(2)
        } else {
            window.location.href = '/gym.php';
        }
    }
    if (step === 2) {
        console.log("doGym step 2");
        if (window.location.pathname != '/gym.php') {
            window.location.href = '/gym.php';
        }
        var Strength = document.getElementById('strengthTotal').innerText;
        var Defense = document.getElementById('defenceTotal').innerText;
        var Speed = document.getElementById('speedTotal').innerText;
        var Dexterity = document.getElementById('dexterityTotal').innerText;

        GM_setValue('gym_step', 1);

        if (Strength <= Defense) {
            document.getElementById('divStrength').getElementsByClassName('numb')[0].value = 1;
            document.getElementById('divStrength').getElementsByClassName('trainStat')[0].click();
        } else if (Defense <= Speed) {
            document.getElementById('divDefence').getElementsByClassName('numb')[0].value = 1;
            document.getElementById('divDefence').getElementsByClassName('trainStat')[0].click();
        } else if (Speed <= Dexterity) {
            document.getElementById('divSpeed').getElementsByClassName('numb')[0].value = 1;
            document.getElementById('divSpeed').getElementsByClassName('trainStat')[0].click();
        } else {
            document.getElementById('divDexterity').getElementsByClassName('numb')[0].value = 1;
            document.getElementById('divDexterity').getElementsByClassName('trainStat')[0].click();
        }

        window.setTimeout(function() {
            var stats = checkStats();
            if (stats['energy'] >= 5) {
                GM_setValue('gym_step', 1);
                doGym(1);
            } else {
                window.location.href = '/index.php';
            }
        }, 1500);
    }
}

function doCrime(step) {
    if (step === 1) {
        console.log("doCrime step 1");
        GM_setValue('crime_step', 2);
        window.location.href = '/crimes.php';
    }
    if (step === 2) {
        console.log("doCrime step 2");
        $('input[name=crime][value=shoplift]').click();
        GM_setValue('crime_step', 3);
    }
    if (step === 3) {
        $('input[name=crime][value=sweetshop]').click();
        GM_setValue('crime_step', 4);
    }
    if (step === 4) {
        $('input[name=crime][value=extrastrongmints]').click();
        GM_setValue('crime_step', 5);
    }
    if (step === 5) {
        GM_setValue('crime_step', 1);
        window.location.href = '/index.php';
    }
}<commit_msg>Changed crime to pickpocket hobo<commit_after>// ==UserScript==
// @name         Torn City automatic Gym and Crime bot
// @namespace    http://liquidpineapple.net
// @version      0.5
// @description  Try to take over the world, for the lazy.
// @author       Jurriaan Den Toonder<jurriaan.toonder@liquidpineapple.net>
// @downloadURL  https://github.com/Fastjur/Torn-City-Bot/raw/master/src/TornCityBot.user.js
// @updateURL    https://github.com/Fastjur/Torn-City-Bot/raw/master/src/TornCityBot.user.js
// @match        http://www.torn.com/*
// @require      http://code.jquery.com/jquery-2.2.2.min.js
// @run-at       document-end
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// ==/UserScript==
'use strict';

$(document).ready(function(){
    console.log("Torn city bot loaded!");
    window.setInterval(init, 2000);
});

function init() {
    var action = GM_getValue('action', 'gym');
    var stats = checkStats();
    if (action === 'gym') {
        GM_setValue('action', 'gym');
        if (stats['energy'] >= 5) {
            console.log("Energy >= 5, doGym()");
            var gymStep = GM_getValue('gym_step', 1);
            doGym(gymStep);
        } else {
            GM_setValue('action', 'crime');
        }
    } else if (action === 'crime') {
        if (stats['nerve'] >= 4) {
            console.log("Nerve >= 4, doCrime()");
            var crimeStep = GM_getValue('crime_step', 1);
            console.log("CRIME STEP: " + crimeStep);
            doCrime(crimeStep);
        } else {
            GM_deleteValue('action');//Cannot do anything
        }
    } else {
        console.error("Invalid action, resetting bot and reloading");
        GM_deleteValue('action');
        window.location.href = '/index.php';
    }
}

function checkStats() {
    var Energy = document.getElementById('energy').children[1].dataset.current;
    var Nerve = document.getElementById('nerve').children[1].dataset.current;
    var Happy = document.getElementById('happy').children[1].dataset.current;
    var Life = document.getElementById('life').children[1].dataset.current;
    return {
        'energy': Energy,
        'nerve': Nerve,
        'happy': Happy,
        'life': Life
    };
}

function doGym(step) {
    if (step === 1) {
        console.log("doGym step 1");
        GM_setValue('gym_step', 2);
        if (window.location.pathname == '/gym.php'){
            doGym(2)
        } else {
            window.location.href = '/gym.php';
        }
    }
    if (step === 2) {
        console.log("doGym step 2");
        if (window.location.pathname != '/gym.php') {
            window.location.href = '/gym.php';
        }
        var Strength = document.getElementById('strengthTotal').innerText;
        var Defense = document.getElementById('defenceTotal').innerText;
        var Speed = document.getElementById('speedTotal').innerText;
        var Dexterity = document.getElementById('dexterityTotal').innerText;

        GM_setValue('gym_step', 1);

        if (Strength <= Defense) {
            document.getElementById('divStrength').getElementsByClassName('numb')[0].value = 1;
            document.getElementById('divStrength').getElementsByClassName('trainStat')[0].click();
        } else if (Defense <= Speed) {
            document.getElementById('divDefence').getElementsByClassName('numb')[0].value = 1;
            document.getElementById('divDefence').getElementsByClassName('trainStat')[0].click();
        } else if (Speed <= Dexterity) {
            document.getElementById('divSpeed').getElementsByClassName('numb')[0].value = 1;
            document.getElementById('divSpeed').getElementsByClassName('trainStat')[0].click();
        } else {
            document.getElementById('divDexterity').getElementsByClassName('numb')[0].value = 1;
            document.getElementById('divDexterity').getElementsByClassName('trainStat')[0].click();
        }

        window.setTimeout(function() {
            var stats = checkStats();
            if (stats['energy'] >= 5) {
                GM_setValue('gym_step', 1);
                doGym(1);
            } else {
                window.location.href = '/index.php';
            }
        }, 1500);
    }
}

function doCrime(step) {
    if (step === 1) {
        console.log("doCrime step 1");
        GM_setValue('crime_step', 2);
        window.location.href = '/crimes.php';
    }
    if (step === 2) {
        console.log("doCrime step 2");
        $('input[name=crime][value=pickpocket]').click();
        GM_setValue('crime_step', 3);
    }
    if (step === 3) {
        $('input[name=crime][value=hobo]').click();
        GM_setValue('crime_step', 4);
    }
    if (step === 4) {
        //$('input[name=crime][value=extrastrongmints]').click();
        GM_setValue('crime_step', 5);
    }
    if (step === 5) {
        GM_setValue('crime_step', 1);
        window.location.href = '/index.php';
    }
}
<|endoftext|>


<commit_before>"use strict";

var grunt = require('grunt');
var path = require('path');
var plugin;

module.exports = function () {
  plugin.initialisePlugin();
};

plugin = {
  initialisePlugin: function () {
    this.registerTasks();
    this.registerHelpers();
  },

  registerTasks: function () {
    this.registerTextReplaceTask();
  },

  registerHelpers: function () {
    this.registerReplaceHelper();
    this.registerTextReplaceHelper();
    this.registerTextReplaceMultipleHelper();
    this.registerTextReplaceFileHelper();
    this.registerTextReplaceFileMultipleHelper();
  },

  registerTextReplaceTask: function () {
    grunt.registerMultiTask('replace',
      'General purpose text replacement for grunt. Allows you to replace ' +
      'text in files using strings, regexs or functions.',
        this.replaceTask);
  },

  replaceTask: function () {
    grunt.helper('replace', {
      src: this.data.src,
      dest: this.data.dest,
      overwrite: this.data.overwrite,
      replacements: this.data.replacements
    });
  },

  registerReplaceHelper: function () {
    grunt.registerHelper('replace',
      this.replaceHelper);
  },

  registerTextReplaceHelper: function () {
    grunt.registerHelper('text-replace',
      this.textReplaceHelper);
  },

  registerTextReplaceMultipleHelper: function () {
    grunt.registerHelper('text-replace-multiple',
      this.textReplaceMultipleHelper);
  },

  registerTextReplaceFileHelper: function () {
    grunt.registerHelper('text-replace-file',
      this.textReplaceFileHelper);
  },

  registerTextReplaceFileMultipleHelper: function () {
    grunt.registerHelper('text-replace-file-multiple',
      this.textReplaceFileMultipleHelper);
  },

  textReplaceHelper: function (fullText, from, to) {
    var regex = plugin.convertPatternToRegex(from);
    var expandedReplacement = plugin.expandReplacement(to);
    return fullText.replace(regex, expandedReplacement);
  },

  textReplaceMultipleHelper: function (fullText, allReplacements) {
    return allReplacements.reduce(function (fullText, replacement) {
      return grunt.helper('text-replace',
        fullText, replacement.from, replacement.to);
    }, fullText);
  },

  textReplaceFileHelper: function (pathToSource, dest, replacements) {
    var pathToDestination = plugin.getPathToDestination(pathToSource, dest);
    grunt.file.copy(pathToSource, pathToDestination, {
      process: function (fullText) {
        return grunt.helper('text-replace-multiple', fullText, replacements);
      }
    });
  },

  getPathToDestination: function (pathToSource, dest) {
    var isDestinationDirectory = (/\/$/).test(dest);
    var fileName = path.basename(pathToSource);
    var pathToDestination;
    if (typeof dest === 'undefined') {
      pathToDestination = pathToSource;
    } else {
      pathToDestination = dest + (isDestinationDirectory ? fileName : '');
    }
    return pathToDestination;
  },

  textReplaceFileMultipleHelper: function (src, dest, replacements) {
    var sourceFiles = grunt.file.expandFiles(src);
    sourceFiles.forEach(function (pathToSource) {
      grunt.helper('text-replace-file', pathToSource, dest, replacements);
    });
  },

  replaceHelper: function (settings) {
    var src = grunt.file.expandFiles(settings.src || []);
    var dest = settings.dest;
    var overwrite = settings.overwrite;
    var replacements = settings.replacements;
    var isDestinationDirectory = (/\/$/).test(dest);
    var initialWarnCount = grunt.fail.warncount;

    if (typeof dest === 'undefined' &&
        typeof src === 'undefined' &&
        typeof replacements === 'undefined') {
      grunt.warn(plugin.errorMessages.noTargetsDefined);
    } else if (src.length === 0) {
      grunt.warn(plugin.errorMessages.noSourceFiles);
    } else if (typeof dest === 'undefined' && overwrite !== true) {
      grunt.warn(plugin.errorMessages.noDestination);
    } else if (typeof replacements === 'undefined') {
      grunt.warn(plugin.errorMessages.noReplacements);
    } else if (typeof dest !== 'undefined' && overwrite === true) {
      grunt.warn(plugin.errorMessages.overwriteFailure);
    } else if ((isDestinationDirectory === false && src.length > 1) && overwrite !== true) {
      grunt.warn(plugin.errorMessages.multipleSourceSingleDestination);
    } else if (grunt.fail.warncount - initialWarnCount === 0) {
      grunt.helper('text-replace-file-multiple', src, dest, replacements);
    }
  },

  errorMessages: {
    noTargetsDefined: "No targets were found. Remember to wrap functionality " +
      "within a target.",
    noSourceFiles: "No source files found",
    noDestination: "Destination is not defined! If you want to overwrite " +
      "files, then make sure to set overwrite: true. If you don't wish to " +
      "overwrite, then make sure to set a destination",
    noReplacements: "No replacements were found.",
    overwriteFailure: "Overwrite is to true, but a destination has also " +
      "been defined. If you want to overwrite files, remove the destination. " +
      "If you want to send files to a destination, then ensure overwrite is " +
      "not set to true",
    multipleSourceSingleDestination: "Cannot write multiple files to same " +
      "file. If you wish to export to a directory, make sure there is a " +
      "trailing slash on the destination. If you wish to write to a single " +
      "file, make sure there is only one source file"
  },

  convertPatternToRegex: function (pattern) {
    var regexCharacters = '\\[](){}^$-.*+?|,/';
    if (typeof pattern === 'string') {
      regexCharacters.split('').forEach(function (character) {
        var characterAsRegex = new RegExp('(\\' + character + ')', 'g');
        pattern = pattern.replace(characterAsRegex, '\\$1');
      });
      pattern = new RegExp(pattern, 'g');
    }
    return pattern;
  },

  expandReplacement: function (replacement) {
    if (typeof replacement === 'function') {
      return this.expandFunctionReplacement(replacement);
    } else if (typeof replacement === 'string') {
      return this.expandStringReplacement(replacement);
    }
  },

  expandFunctionReplacement: function (replacement) {
    return function () {
      var matchedSubstring = arguments[0];
      var index = arguments[arguments.length - 2];
      var fullText = arguments[arguments.length - 1];
      var regexMatches = Array.prototype.slice.call(arguments, 1,
        arguments.length - 2);
      var returnValue = replacement(matchedSubstring, index, fullText,
        regexMatches);
      return (typeof returnValue === 'string') ?
        grunt.template.process(returnValue) : returnValue;
    };
  },

  expandStringReplacement: function (replacement) {
    return grunt.template.process(replacement);
  }
};

<commit_msg>Modified code to work for both locally and globally installed instances of grunt, on advice from Craga89<commit_after>"use strict";

var grunt;
var path = require('path');
var plugin;

module.exports = function (referenceToGrunt) {
  grunt = referenceToGrunt;
  plugin.initialisePlugin();
};

plugin = {
  initialisePlugin: function () {
    this.registerTasks();
    this.registerHelpers();
  },

  registerTasks: function () {
    this.registerTextReplaceTask();
  },

  registerHelpers: function () {
    this.registerReplaceHelper();
    this.registerTextReplaceHelper();
    this.registerTextReplaceMultipleHelper();
    this.registerTextReplaceFileHelper();
    this.registerTextReplaceFileMultipleHelper();
  },

  registerTextReplaceTask: function () {
    grunt.registerMultiTask('replace',
      'General purpose text replacement for grunt. Allows you to replace ' +
      'text in files using strings, regexs or functions.',
        this.replaceTask);
  },

  replaceTask: function () {
    grunt.helper('replace', {
      src: this.data.src,
      dest: this.data.dest,
      overwrite: this.data.overwrite,
      replacements: this.data.replacements
    });
  },

  registerReplaceHelper: function () {
    grunt.registerHelper('replace',
      this.replaceHelper);
  },

  registerTextReplaceHelper: function () {
    grunt.registerHelper('text-replace',
      this.textReplaceHelper);
  },

  registerTextReplaceMultipleHelper: function () {
    grunt.registerHelper('text-replace-multiple',
      this.textReplaceMultipleHelper);
  },

  registerTextReplaceFileHelper: function () {
    grunt.registerHelper('text-replace-file',
      this.textReplaceFileHelper);
  },

  registerTextReplaceFileMultipleHelper: function () {
    grunt.registerHelper('text-replace-file-multiple',
      this.textReplaceFileMultipleHelper);
  },

  textReplaceHelper: function (fullText, from, to) {
    var regex = plugin.convertPatternToRegex(from);
    var expandedReplacement = plugin.expandReplacement(to);
    return fullText.replace(regex, expandedReplacement);
  },

  textReplaceMultipleHelper: function (fullText, allReplacements) {
    return allReplacements.reduce(function (fullText, replacement) {
      return grunt.helper('text-replace',
        fullText, replacement.from, replacement.to);
    }, fullText);
  },

  textReplaceFileHelper: function (pathToSource, dest, replacements) {
    var pathToDestination = plugin.getPathToDestination(pathToSource, dest);
    grunt.file.copy(pathToSource, pathToDestination, {
      process: function (fullText) {
        return grunt.helper('text-replace-multiple', fullText, replacements);
      }
    });
  },

  getPathToDestination: function (pathToSource, dest) {
    var isDestinationDirectory = (/\/$/).test(dest);
    var fileName = path.basename(pathToSource);
    var pathToDestination;
    if (typeof dest === 'undefined') {
      pathToDestination = pathToSource;
    } else {
      pathToDestination = dest + (isDestinationDirectory ? fileName : '');
    }
    return pathToDestination;
  },

  textReplaceFileMultipleHelper: function (src, dest, replacements) {
    var sourceFiles = grunt.file.expandFiles(src);
    sourceFiles.forEach(function (pathToSource) {
      grunt.helper('text-replace-file', pathToSource, dest, replacements);
    });
  },

  replaceHelper: function (settings) {
    var src = grunt.file.expandFiles(settings.src || []);
    var dest = settings.dest;
    var overwrite = settings.overwrite;
    var replacements = settings.replacements;
    var isDestinationDirectory = (/\/$/).test(dest);
    var initialWarnCount = grunt.fail.warncount;

    if (typeof dest === 'undefined' &&
        typeof src === 'undefined' &&
        typeof replacements === 'undefined') {
      grunt.warn(plugin.errorMessages.noTargetsDefined);
    } else if (src.length === 0) {
      grunt.warn(plugin.errorMessages.noSourceFiles);
    } else if (typeof dest === 'undefined' && overwrite !== true) {
      grunt.warn(plugin.errorMessages.noDestination);
    } else if (typeof replacements === 'undefined') {
      grunt.warn(plugin.errorMessages.noReplacements);
    } else if (typeof dest !== 'undefined' && overwrite === true) {
      grunt.warn(plugin.errorMessages.overwriteFailure);
    } else if ((isDestinationDirectory === false && src.length > 1) && overwrite !== true) {
      grunt.warn(plugin.errorMessages.multipleSourceSingleDestination);
    } else if (grunt.fail.warncount - initialWarnCount === 0) {
      grunt.helper('text-replace-file-multiple', src, dest, replacements);
    }
  },

  errorMessages: {
    noTargetsDefined: "No targets were found. Remember to wrap functionality " +
      "within a target.",
    noSourceFiles: "No source files found",
    noDestination: "Destination is not defined! If you want to overwrite " +
      "files, then make sure to set overwrite: true. If you don't wish to " +
      "overwrite, then make sure to set a destination",
    noReplacements: "No replacements were found.",
    overwriteFailure: "Overwrite is to true, but a destination has also " +
      "been defined. If you want to overwrite files, remove the destination. " +
      "If you want to send files to a destination, then ensure overwrite is " +
      "not set to true",
    multipleSourceSingleDestination: "Cannot write multiple files to same " +
      "file. If you wish to export to a directory, make sure there is a " +
      "trailing slash on the destination. If you wish to write to a single " +
      "file, make sure there is only one source file"
  },

  convertPatternToRegex: function (pattern) {
    var regexCharacters = '\\[](){}^$-.*+?|,/';
    if (typeof pattern === 'string') {
      regexCharacters.split('').forEach(function (character) {
        var characterAsRegex = new RegExp('(\\' + character + ')', 'g');
        pattern = pattern.replace(characterAsRegex, '\\$1');
      });
      pattern = new RegExp(pattern, 'g');
    }
    return pattern;
  },

  expandReplacement: function (replacement) {
    if (typeof replacement === 'function') {
      return this.expandFunctionReplacement(replacement);
    } else if (typeof replacement === 'string') {
      return this.expandStringReplacement(replacement);
    }
  },

  expandFunctionReplacement: function (replacement) {
    return function () {
      var matchedSubstring = arguments[0];
      var index = arguments[arguments.length - 2];
      var fullText = arguments[arguments.length - 1];
      var regexMatches = Array.prototype.slice.call(arguments, 1,
        arguments.length - 2);
      var returnValue = replacement(matchedSubstring, index, fullText,
        regexMatches);
      return (typeof returnValue === 'string') ?
        grunt.template.process(returnValue) : returnValue;
    };
  },

  expandStringReplacement: function (replacement) {
    return grunt.template.process(replacement);
  }
};

<|endoftext|>