code/dataobjects/FusionTag.php
public function requireDefaultRecords() {

		parent::requireDefaultRecords();

		// This isn't required during testing.

		if(Controller::has_curr() && (Controller::curr() instanceof TestRunner)) {
			return;
		}

		// Retrieve existing and configuration defined tag types that have not been consolidated.

		$wrapped = array();
		foreach($this->service->getFusionTagTypes() as $type => $field) {
			if(($tags = $type::get()->filter('FusionTagID', 0)) && $tags->exists()) {
				foreach($tags as $tag) {

					// Determine whether there's an existing fusion tag.

					if(!($existing = FusionTag::get()->filter('Title', $tag->$field)->first())) {

						// There is no fusion tag, therefore instantiate one using the current tag.

						$fusion = FusionTag::create();
						$fusion->Title = $tag->$field;
						$fusion->TagTypes = serialize(array(
							$tag->ClassName => $tag->ClassName
						));
						$fusion->write();
						$fusionID = $fusion->ID;
						DB::alteration_message("\"{$tag->$field}\" Fusion Tag", 'created');
					}
					else {

						// There is a fusion tag, therefore append the current tag type.

						$types = unserialize($existing->TagTypes);
						$types[$tag->ClassName] = $tag->ClassName;
						$existing->TagTypes = serialize($types);
						$existing->write();
						$fusionID = $existing->ID;
					}

					// Update the current tag to point to this.

					$tag->FusionTagID = $fusionID;
					$tag->write();
				}
			}

			// The existing and configuration defined tag types need to be wrapped for serialised partial matching.

			$wrapped[] = "\"{$type}\"";
		}

		// Determine whether tag type exclusions have caused any fusion tags to become redundant.

		$tags = FusionTag::get()->where('TagTypes IS NOT NULL');
		if(count($wrapped)) {

			// Determine the fusion tags that only contain tag type exclusions.

			$tags = $tags->exclude('TagTypes:PartialMatch', $wrapped);
		}
		if($tags->exists()) {

			// Determine any data objects with the tagging extension.

			$objects = array();
			$configuration = Config::inst();
			$classes = ClassInfo::subclassesFor('DataObject');
			unset($classes['DataObject']);
			foreach($classes as $class) {

				// Determine the specific data object extensions.

				$extensions = $configuration->get($class, 'extensions', Config::UNINHERITED);
				if(is_array($extensions) && in_array('TaggingExtension', $extensions)) {
					$objects[] = $class;
				}
			}

			// Determine whether these fusion tags are now redundant.

			$mode = Versioned::get_reading_mode();
			Versioned::reading_stage('Stage');
			$types = array();
			$where = array();
			foreach($tags as $tag) {

				// Determine whether this fusion tag is being used.

				$ID = $tag->ID;
				foreach($objects as $object) {
					if($object::get()->filter('FusionTags.ID', $ID)->exists()) {

						// This fusion tag is being used, so keep it.

						continue 2;
					}
				}

				// These fusion tags are now redundant.

				$types = array_merge($types, unserialize($tag->TagTypes));
				$where[] = array(
					'FusionTagID' => $ID
				);
				$tag->delete();
				DB::alteration_message("\"{$tag->Title}\" Fusion Tag", 'deleted');
			}
			Versioned::set_reading_mode($mode);

			// The tag type exclusions need updating to reflect this.

			foreach($types as $exclusion) {
				$query = new SQLUpdate(
					$exclusion,
					array(
						'FusionTagID' => 0
					),
					$where
				);
				$query->useDisjunction();
				$query->execute();
			}
		}
	}
public function requireDefaultRecords() {

		parent::requireDefaultRecords();

		// This isn't required during testing.

		if(Controller::has_curr() && (Controller::curr() instanceof TestRunner)) {
			return;
		}

		// Retrieve existing and configuration defined tag types that have not been consolidated.

		$wrapped = array();
		foreach($this->service->getFusionTagTypes() as $type => $field) {
			if(($tags = $type::get()->filter('FusionTagID', 0)) && $tags->exists()) {
				foreach($tags as $tag) {

					// Determine whether there's an existing fusion tag.

					if(!($existing = FusionTag::get()->filter('Title', $tag->$field)->first())) {

						// There is no fusion tag, therefore instantiate one using the current tag.

						$fusion = FusionTag::create();
						$fusion->Title = $tag->$field;
						$fusion->TagTypes = serialize(array(
							$tag->ClassName => $tag->ClassName
						));
						$fusion->write();
						$fusionID = $fusion->ID;
						DB::alteration_message("\"{$tag->$field}\" Fusion Tag", 'created');
					}
					else {

						// There is a fusion tag, therefore append the current tag type.

						$types = unserialize($existing->TagTypes);
						$types[$tag->ClassName] = $tag->ClassName;
						$existing->TagTypes = serialize($types);
						$existing->write();
						$fusionID = $existing->ID;
					}

					// Update the current tag to point to this.

					$tag->FusionTagID = $fusionID;
					$tag->write();
				}
			}

			// The existing and configuration defined tag types need to be wrapped for serialised partial matching.

			$wrapped[] = "\"{$type}\"";
		}

		// Determine whether tag type exclusions have caused any fusion tags to become redundant.

		$tags = FusionTag::get()->where('TagTypes IS NOT NULL');
		if(count($wrapped)) {

			// Determine the fusion tags that only contain tag type exclusions.

			$tags = $tags->exclude('TagTypes:PartialMatch', $wrapped);
		}
		if($tags->exists()) {

			// Determine any data objects with the tagging extension.

			$objects = array();
			$configuration = Config::inst();
			$classes = ClassInfo::subclassesFor('DataObject');
			unset($classes['DataObject']);
			foreach($classes as $class) {

				// Determine the specific data object extensions.

				$extensions = $configuration->get($class, 'extensions', Config::UNINHERITED);
				if(is_array($extensions) && in_array('TaggingExtension', $extensions)) {
					$objects[] = $class;
				}
			}

			// Determine whether these fusion tags are now redundant.

			$mode = Versioned::get_reading_mode();
			Versioned::reading_stage('Stage');
			$types = array();
			$where = array();
			foreach($tags as $tag) {

				// Determine whether this fusion tag is being used.

				$ID = $tag->ID;
				foreach($objects as $object) {
					if($object::get()->filter('FusionTags.ID', $ID)->exists()) {

						// This fusion tag is being used, so keep it.

						continue 2;
					}
				}

				// These fusion tags are now redundant.

				$types = array_merge($types, unserialize($tag->TagTypes));
				$where[] = array(
					'FusionTagID' => $ID
				);
				$tag->delete();
				DB::alteration_message("\"{$tag->Title}\" Fusion Tag", 'deleted');
			}
			Versioned::set_reading_mode($mode);

			// The tag type exclusions need updating to reflect this.

			foreach($types as $exclusion) {
				$query = new SQLUpdate(
					$exclusion,
					array(
						'FusionTagID' => 0
					),
					$where
				);
				$query->useDisjunction();
				$query->execute();
			}
		}
	}
The process to automatically consolidate existing and configuration defined tag types, executed on project build.