diff --git a/src/Command/SeedFakeDevicesCommand.php b/src/Command/SeedFakeDevicesCommand.php new file mode 100644 index 0000000..29bc993 --- /dev/null +++ b/src/Command/SeedFakeDevicesCommand.php @@ -0,0 +1,123 @@ +addArgument('email', InputArgument::REQUIRED, 'Account email') + ->addOption('remove', null, InputOption::VALUE_NONE, 'Remove previously-seeded fake devices and exit'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $email = (string) $input->getArgument('email'); + + $user = $this->em->getRepository(User::class)->findOneBy(['email' => $email]); + if ($user === null) { + $io->error("No user found with email '$email'."); + return Command::FAILURE; + } + + // Always sweep prior fakes first (re-runs stay idempotent). + $existing = $this->em->getRepository(Device::class)->createQueryBuilder('d') + ->where('d.user = :u AND d.mac LIKE :prefix') + ->setParameter('u', $user) + ->setParameter('prefix', self::FAKE_MAC_PREFIX . '%') + ->getQuery() + ->getResult(); + foreach ($existing as $d) { + $this->em->remove($d); + } + if ($existing) { + $this->em->flush(); + $io->writeln(sprintf('Removed %d existing fake device(s).', count($existing))); + } + + if ($input->getOption('remove')) { + $io->success('Done.'); + return Command::SUCCESS; + } + + // Five fakes covering each status state. + $now = new \DateTimeImmutable(); + $fakes = [ + ['name' => 'Living Room', 'orientation' => Orientation::Landscape, 'lastSeen' => 'PT5M', 'wakeHour' => null], + ['name' => 'Kitchen', 'orientation' => Orientation::Landscape, 'lastSeen' => 'PT90M', 'wakeHour' => null], + ['name' => 'Bedroom', 'orientation' => Orientation::Portrait, 'lastSeen' => 'P3D', 'wakeHour' => null], + ['name' => "Mom's Place", 'orientation' => Orientation::Portrait, 'lastSeen' => null, 'wakeHour' => null], + ['name' => 'Cabin', 'orientation' => Orientation::Landscape, 'lastSeen' => 'PT1H', 'wakeHour' => 4], + ]; + + $reflLastSeen = new \ReflectionProperty(Device::class, 'lastSeenAt'); + $reflLastSeen->setAccessible(true); + + foreach ($fakes as $i => $cfg) { + $device = new Device(); + $device->setMac(sprintf(self::FAKE_MAC_PREFIX . '%02X', $i + 1)); + $device->setName($cfg['name']); + $device->setModel(DeviceModel::V1); + $device->setOrientation($cfg['orientation']); + $device->setRotationIntervalMinutes(60); + $device->setTimezone('America/New_York'); + $device->setUser($user); + if ($cfg['wakeHour'] !== null) { + $device->setWakeHour($cfg['wakeHour']); + } + if ($cfg['lastSeen'] !== null) { + $reflLastSeen->setValue($device, $now->sub(new \DateInterval($cfg['lastSeen']))); + } + $this->em->persist($device); + + $io->writeln(sprintf( + ' + %s — %s, %s', + $cfg['name'], + $cfg['orientation']->value, + $cfg['lastSeen'] === null ? 'never seen' : 'last seen ' . $cfg['lastSeen'] . ' ago', + )); + } + + $this->em->flush(); + $io->success(sprintf('Seeded %d fake devices for %s.', count($fakes), $email)); + return Command::SUCCESS; + } +}