/ src / Controller / ServerController.php
ServerController.php
  1  <?php
  2  
  3  namespace App\Controller;
  4  
  5  use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  6  use Symfony\Contracts\Translation\TranslatorInterface;
  7  
  8  use Symfony\Component\Routing\Annotation\Route;
  9  use Symfony\Component\HttpFoundation\Response;
 10  use Symfony\Component\HttpFoundation\Request;
 11  
 12  use App\Entity\Online;
 13  use App\Entity\Player;
 14  use App\Entity\Server;
 15  use Doctrine\ORM\EntityManagerInterface;
 16  
 17  class ServerController extends AbstractController
 18  {
 19      #[Route(
 20          '/server/{crc32server}',
 21          name: 'server_index',
 22          requirements:
 23          [
 24              'crc32server' => '\d+',
 25          ],
 26          methods:
 27          [
 28              'GET'
 29          ]
 30      )]
 31      public function index(
 32          ?Request $request,
 33          EntityManagerInterface $entityManagerInterface
 34      ): Response
 35      {
 36          // Validate server
 37          $server = $entityManagerInterface->getRepository(Server::class)->findOneBy(
 38              [
 39                  'crc32server' => $request->get('crc32server')
 40              ]
 41          );
 42  
 43          if (!$server)
 44          {
 45              throw $this->createNotFoundException();
 46          }
 47  
 48          // Prepare page request
 49          if ($request->get('page') && (int) $request->get('page') > 1)
 50          {
 51              $page = (int) $request->get('page');
 52          }
 53  
 54          else
 55          {
 56              $page = 1;
 57          }
 58  
 59          // Init defaults
 60          $info    = [];
 61          $session = [];
 62  
 63          // Get online
 64          $online = $entityManagerInterface->getRepository(Online::class)->findBy(
 65              [
 66                  'crc32server' => $server->getCrc32server()
 67              ],
 68              [
 69                  'online' == $request->get('sort') && in_array($request->get('field'), ['time','players','bots','total'])
 70                  ? $request->get('field') : 'time' => in_array($request->get('order'), ['asc','desc']) ? $request->get('order') : 'desc',
 71              ],
 72              $this->getParameter('app.server.online.limit'),
 73              'online' == $request->get('sort') ? ($page - 1) * $this->getParameter('app.server.online.limit') : 0
 74          );
 75  
 76          // Get players
 77          $players = $entityManagerInterface->getRepository(Player::class)->findBy(
 78              [
 79                  'crc32server' => $server->getCrc32server()
 80              ],
 81              [
 82                  'players' == $request->get('sort') && in_array($request->get('field'), ['name','frags','joined','online'])
 83                  ? $request->get('field') : 'frags' => in_array($request->get('order'), ['asc','desc']) ? $request->get('order') : 'desc',
 84              ],
 85              $this->getParameter('app.server.players.limit'),
 86              'players' == $request->get('sort') ? ($page - 1) * $this->getParameter('app.server.players.limit') : 0
 87          );
 88  
 89          // Format address
 90          if (false === filter_var($server->getHost(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
 91          {
 92              $address = "{$server->getHost()}:{$server->getPort()}";
 93          }
 94  
 95          else
 96          {
 97              $address = "[{$server->getHost()}]:{$server->getPort()}";
 98          }
 99  
100          // Request server info
101          try
102          {
103              $node = new \xPaw\SourceQuery\SourceQuery();
104  
105              $node->Connect(
106                  false === filter_var($server->getHost(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? $server->getHost() : "[{$server->getHost()}]",
107                  $server->getPort(),
108                  1
109              );
110  
111              if ($node->Ping())
112              {
113                  if ($info = (array) $node->GetInfo())
114                  {
115                      // Get session
116                      $session = empty($info['Players']) ? [] : (array) $node->GetPlayers();
117  
118                      // Sort by players by frags
119                      if ($session)
120                      {
121                          array_multisort(
122                              array_column(
123                                  $session,
124                                  'Frags'
125                              ),
126                              SORT_DESC,
127                              $session
128                          );
129                      }
130                  }
131  
132                  $status = true;
133              }
134  
135              else
136              {
137                  $status = false;
138              }
139          }
140  
141          catch (Exception $error)
142          {
143              throw $this->createNotFoundException();
144          }
145  
146          catch (\Throwable $error)
147          {
148              $status = false;
149          }
150  
151          finally
152          {
153              $node->Disconnect();
154          }
155  
156          return $this->render(
157              'default/server/index.html.twig',
158              [
159                  'request' => $request,
160                  'server' =>
161                  [
162                      'address'     => $address,
163                      'crc32server' => $server->getCrc32server(),
164                      'name'        => $server->getName(),
165                      'host'        => $server->getHost(),
166                      'port'        => $server->getPort(),
167                      'info'        => $info,
168                      'session'     => $session,
169                      'online'      => $online,
170                      'players'     => $players,
171                      'status'      => $status,
172                      'pagination'  =>
173                      [
174                          'players' => ceil(
175                              $entityManagerInterface->getRepository(Player::class)->getTotalByCrc32server(
176                                  $server->getCrc32server()
177                              ) / $this->getParameter('app.server.players.limit')
178                          ),
179                          'online'  => ceil(
180                              $entityManagerInterface->getRepository(Online::class)->getTotalByCrc32server(
181                                  $server->getCrc32server()
182                              ) / $this->getParameter('app.server.online.limit')
183                          )
184                      ],
185                      'connections' => empty($info['Players']) || $info['Players'] < 0 || empty($info['Bots']) || $info['Bots'] < 0
186                                       ? 0
187                                       : (int) $info['Players'] - (int) $info['Bots']
188                  ]
189              ]
190          );
191      }
192  }