Source of file CommonAncestor.php
Size: 2,986 Bytes - Last Modified: 2021-12-24T06:48:20+00:00
/var/www/docs.ssmods.com/process/src/src/CommonAncestor.php
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 | <?php namespace Fromholdio\CommonAncestor; use SilverStripe\Core\ClassInfo; class CommonAncestor { /** * Accepts an array of class names, whose ancestries will be compared, to identify * their closest common ancestor class. * * @param array $classes Array of class names to find a common ancestor for. * @param boolean $tablesOnly Only include classes that have a table in the database. * * @return string Common ancestor class name. */ public static function get_closest(array $classes, $tablesOnly = false) { if (empty($classes)) { throw new \InvalidArgumentException( 'You must provide at least one class in your $classes array.' ); } foreach ($classes as $class) { if (!ClassInfo::exists($class)) { throw new \InvalidArgumentException( 'Invalid class provided to CommonAncestor::get_closest().' . $class . ' does not exist.' ); } } if (count($classes) === 1) { return reset($classes); } /* * Loop over each class, making a list of all ancestor classes, * building a count of how many times each class appears in ancestry. */ $ancestors = []; foreach ($classes as $class) { $myAncestors = ClassInfo::ancestry($class, $tablesOnly); foreach ($myAncestors as $myAncestor) { if (isset($ancestors[$myAncestor])) { $ancestors[$myAncestor] = $ancestors[$myAncestor] + 1; } else { $ancestors[$myAncestor] = 1; } } } /* * Ancestor classes are common if their count is equal to the total supplied classes * (these are the classes that all supplied classes share in their ancestry trees) */ foreach ($ancestors as $ancestorClass => $ancestorCount) { // Remove classes that do not appear in ancestry of all supplied classes if ($ancestorCount !== count($classes)) { unset($ancestors[$ancestorClass]); } } /* * If only one ancestor class remains, return that value */ if (count($ancestors) === 1) { return current(array_flip($ancestors)); } /* * If more than one ancestor class, determine which is closest in hierarchy * to the supplied classes. To do this we simply use the first of the supplied * classes and walk through its ancestry until we find the first match. */ $myAncestors = array_reverse(ClassInfo::ancestry(reset($classes)), $tablesOnly); foreach ($myAncestors as $myAncestor) { if (array_key_exists($myAncestor, $ancestors)) { return $myAncestor; } } } } |