Files
iD/modules/validations/issue_manager.js
Quincy Morgan 957eb28242 Don't run other validators if feature is missing tags
Don't run disconnected highway check if there is an almost junction issue already
Only run way validators on ways
2019-01-30 17:59:23 -05:00

130 lines
4.4 KiB
JavaScript

import { dispatch as d3_dispatch } from 'd3-dispatch';
import _map from 'lodash-es/map';
import _flatten from 'lodash-es/flatten';
import _flattenDeep from 'lodash-es/flattenDeep';
import _uniq from 'lodash-es/uniq';
import _uniqWith from 'lodash-es/uniqWith';
import { utilRebind } from '../util/rebind';
import * as validations from '../validations/index';
export function IssueManager(context) {
var dispatch = d3_dispatch('reload'),
self = {},
issues = [],
issuesByEntityId = {};
self.featureApplicabilityOptions = ['edited', 'all'];
var featureApplicability = context.storage('issue-features') || 'edited';
self.getFeatureApplicability = function() {
return featureApplicability;
};
self.setFeatureApplicability = function(applicability) {
featureApplicability = applicability;
context.storage('issue-features', applicability);
};
self.getIssues = function() {
return issues;
};
self.getWarnings = function() {
return issues.filter(function(issue) {
return issue.severity === 'warning';
});
};
self.getErrors = function() {
return issues.filter(function(issue) {
return issue.severity === 'error';
});
};
self.getIssuesForEntityWithID = function(entityID) {
if (!context.hasEntity(entityID)) {
return [];
}
if (!issuesByEntityId[entityID]) {
var entity = context.entity(entityID);
issuesByEntityId[entityID] = validateEntity(entity);
}
return issuesByEntityId[entityID];
};
var genericEntityValidations = [
validations.validationDeprecatedTag(),
validations.validationGenericName(),
validations.validationMapCSSChecks(),
validations.validationOldMultipolygon()
];
function validateEntity(entity) {
var issues = [];
// runs validation and appends resulting issues, returning true if validation passed
function runValidation(fn) {
var typeIssues = fn(entity, context);
issues = issues.concat(typeIssues);
return typeIssues.length === 0;
}
// other validations require feature to be tagged
if (!runValidation(validations.validationMissingTag())) return issues;
if (entity.type === 'way') {
if (runValidation(validations.validationHighwayAlmostJunction())) {
// only check for disconnected highway if no almost junctions
runValidation(validations.validationDisconnectedHighway());
}
runValidation(validations.validationHighwayCrossingOtherWays());
runValidation(validations.validationTagSuggestsArea());
}
genericEntityValidations.forEach(function(fn) {
runValidation(fn);
})
return issues;
}
self.validate = function() {
// clear cached issues
issuesByEntityId = {};
issues = [];
var history = context.history();
var changes = history.changes();
var entitiesToCheck = changes.created.concat(changes.modified);
var graph = history.graph();
issues = issues.concat(validations.validationManyDeletions()(changes, context));
entitiesToCheck = _uniq(_flattenDeep(_map(entitiesToCheck, function(entity) {
var entities = [entity];
if (entity.type === 'node') {
// validate ways if their nodes have changed
entities = entities.concat(graph.parentWays(entity));
}
entities = _map(entities, function(entity) {
if (entity.type !== 'relation') {
// validate relations if their geometries have changed
return [entity].concat(graph.parentRelations(entity));
}
return entity;
});
return entities;
})));
for (var entityIndex in entitiesToCheck) {
var entity = entitiesToCheck[entityIndex];
var entityIssues = validateEntity(entity);
issuesByEntityId[entity.id] = entityIssues;
issues = issues.concat(entityIssues);
}
issues = _uniqWith(issues, function(issue1, issue2) {
return issue1.id() === issue2.id();
});
dispatch.call('reload', self, issues);
};
return utilRebind(self, dispatch, 'on');
}