src/App/Subscriber/OneRoster/OneRosterUserProcessSubscriber.php line 58

Open in your IDE?
  1. <?php
  2. namespace App\Subscriber\OneRoster;
  3. use App\Entity\System\School;
  4. use App\Util\Booleans;
  5. use Cms\CoreBundle\Entity\OneRoster\OneRosterUser;
  6. use Cms\CoreBundle\Entity\OneRosterSync;
  7. use Cms\CoreBundle\Events\OneRosterProcessEvent;
  8. use Cms\CoreBundle\Model\Interfaces\OneRosterable\AbstractOneRosterableSubscriber;
  9. use Cms\CoreBundle\Service\Slugger;
  10. use Cms\CoreBundle\Util\Doctrine\EntityManager;
  11. use Cms\ModuleBundle\Service\DraftManager;
  12. use Cms\Modules\PeopleBundle\Entity\Profile\ProfileProxy;
  13. use Doctrine\Common\Util\ClassUtils;
  14. use Symfony\Contracts\Translation\TranslatorInterface;
  15. /**
  16.  */
  17. final class OneRosterUserProcessSubscriber extends AbstractOneRosterableSubscriber
  18. {
  19.     // DI
  20.     protected DraftManager $dm;
  21.     /**
  22.      * @param EntityManager $em
  23.      * @param TranslatorInterface $translator
  24.      * @param DraftManager $dm
  25.      */
  26.     public function __construct(
  27.         EntityManager $em,
  28.         TranslatorInterface $translator,
  29.         DraftManager $dm
  30.     )
  31.     {
  32.         parent::__construct(
  33.             $em,
  34.             $translator
  35.         );
  36.         $this->dm $dm;
  37.     }
  38.     /**
  39.      * {@inheritdoc}
  40.      */
  41.     static public function getSubscribedEvents(): array
  42.     {
  43.         return array(
  44.             OneRosterProcessEvent::EVENT__USER => array(
  45.                 array('peopleModuleSync'0),
  46.             ),
  47.         );
  48.     }
  49.     /**
  50.      * @param OneRosterProcessEvent $event
  51.      */
  52.     public function peopleModuleSync(OneRosterProcessEvent $event): void
  53.     {
  54.         // ensure we are meant to process this
  55.         if ( ! $this->checkTypes($event->getSync(), array(
  56.             OneRosterSync::STRATEGIES__DIRECTORIES,
  57.         ))) {
  58.             return;
  59.         }
  60.         // get the user
  61.         $user $event->getEntity();
  62.         if ( ! $user instanceof OneRosterUser) {
  63.             throw new \Exception(sprintf(
  64.                 'User is not of proper type, got "%s".',
  65.                 ClassUtils::getClass($user)
  66.             ));
  67.         }
  68.         // branch on the role type
  69.         switch (true) {
  70.             case $this->checkTypes($event->getSync(), [OneRosterSync::STRATEGIES__DIRECTORIES]) && $user->isRoleStaff():
  71.                 break;
  72.             default:
  73.                 // DEBUGGING
  74.                 $event->getOutput()->writeln(sprintf(
  75.                     'User role for #%s is "%s", skipping...',
  76.                     $user->getSourcedId(),
  77.                     $user->getRole()
  78.                 ));
  79.                 return;
  80.         }
  81.         // get the org ids for the user
  82.         $sourcedIds array_map(
  83.             function (array $org) {
  84.                 return $org['sourcedId'];
  85.             },
  86.             $user->getOrgs()
  87.         );
  88.         // TODO: can't quit early as we may need to remove schools that don't belong...
  89.         // if no ids, need to quit
  90.         if ( ! $sourcedIds) {
  91.             return;
  92.         }
  93.         // find the schools tied to these orgs
  94.         // we may have missing schools, so that's not anything to worry about really
  95.         // maybe someday we will treat it as more of an error or something
  96.         $schools $this->em->getRepository(School::class)->findBy([
  97.             'oneRosterOrg' => $sourcedIds,
  98.         ]);
  99.         // we need to filter out schools that do not have web departments hooked up to them
  100.         $schools array_values(array_filter(array_map(
  101.             function (School $school) {
  102.                 return $school->getDepartment() ? $school null;
  103.             },
  104.             $schools
  105.         )));
  106.         // if no schools, just quit, makes for easier debugging
  107.         if ( ! $schools) {
  108.             return;
  109.         }
  110.         // now we should have schools with web departments
  111.         // loop over each
  112.         /** @var School $school */
  113.         foreach ($schools as $school) {
  114.             // attempt to find a people entry in the given web department
  115.             // first try to match by oneroster id
  116.             $proxy $this->em->getRepository(ProfileProxy::class)->findOneBy([
  117.                 'container' => $school->getDepartment(),
  118.                 'onerosterId' => $user->getSourcedId(),
  119.             ]);
  120.             // if not found by oneroster id, try again by email
  121.             if ( ! $proxy) {
  122.                 // user must have an email address to progress further
  123.                 if ( ! $user->getEmail()) {
  124.                     return;
  125.                 }
  126.                 // find by email match
  127.                 $proxy $this->em->getRepository(ProfileProxy::class)->findOneBy([
  128.                     'container' => $school->getDepartment(),
  129.                     'data_email' => $user->getEmail(),
  130.                 ]);
  131.             }
  132.             // if we have one, but we are flagged for deletion, we need to remove the proxy or something
  133.             if ($proxy && $user->isStatusToBeDeleted()) {
  134.                 // TODO: should we discard so we don't lose other info, or just delete?
  135.             }
  136.             // if we still don't have one, we have to make one
  137.             if ( ! $proxy instanceof ProfileProxy) {
  138.                 $proxy = new ProfileProxy();
  139.             }
  140.             // need to generate the slug
  141.             $slug Slugger::slug(trim(implode(' ', [
  142.                 $user->getGivenName(),
  143.                 $user->getFamilyName(),
  144.             ])));
  145.             // need to determine if we really need to update this thing or not to save db entries
  146.             $updated = [
  147.                 ($proxy->getOneRosterId() !== $user->getSourcedId()),
  148.                 ($proxy->getOneRosterArchived() !== $user->isStatusToBeDeleted()),
  149.                 ($proxy->getData()->getEmail() !== $user->getEmail()),
  150.                 ($proxy->getData()->getFirstName() !== $user->getGivenName()),
  151.                 ($proxy->getData()->getLastName() !== $user->getFamilyName()),
  152.                 ($proxy->getData()->getSlug() !== $slug),
  153.                 ($proxy->getData()->getTitle() !== $user->getRole()),
  154.             ];
  155.             // if nothing to do, and we are not new, skip
  156.             if ($proxy->getId() && ! Booleans::orX(...$updated)) {
  157.                 // DEBUGGING
  158.                 $event->getOutput()->writeln(sprintf(
  159.                     '    %s    %s (PEOPLE MODULE PROFILE %s | %s | %s)',
  160.                     'Skipping',
  161.                     ClassUtils::getClass($proxy),
  162.                     $proxy->getData()->getEmail(),
  163.                     $proxy->getOneRosterId(),
  164.                     $proxy->getId() ?: '-'
  165.                 ));
  166.                 continue;
  167.             }
  168.             // set things
  169.             $proxy
  170.                 ->setOneRosterId($user->getSourcedId())
  171.                 ->setOneRosterArchived($user->isStatusToBeDeleted())
  172.                 ->getData()
  173.                     ->setEmail($user->getEmail())
  174.                     ->setFirstName($user->getGivenName())
  175.                     ->setLastName($user->getFamilyName())
  176.                     ->setSlug($slug)
  177.                     ->setTitle($user->getRole())
  178.             ;
  179.             // DEBUGGING
  180.             $event->getOutput()->writeln(sprintf(
  181.                 '    %s    %s (PEOPLE MODULE PROFILE %s | %s | %s)',
  182.                 (empty($proxy->getId())) ? 'Generating' 'Updating',
  183.                 ClassUtils::getClass($proxy),
  184.                 $proxy->getData()->getEmail(),
  185.                 $proxy->getOneRosterId(),
  186.                 $proxy->getId() ?: '-'
  187.             ));
  188.             // use the draft manager to save the object
  189.             if ( ! $proxy->getId()) {
  190.                 $this->dm->createProxy($school->getDepartment(), $proxy->getData());
  191.             } else {
  192.                 $this->dm->modifyProxy($proxy$proxy->getData());
  193.             }
  194.         }
  195.     }
  196. }