src/Controller/AdminController.php line 57

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  4. use Symfony\Component\Routing\Annotation\Route;
  5. use Symfony\Component\Process\Exception\ProcessFailedException;
  6. use Symfony\Component\Process\Process;
  7. use Symfony\Component\Yaml\Yaml;
  8. use Symfony\Component\HttpFoundation\Request;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\HttpFoundation\JsonResponse;
  11. use Symfony\Component\Serializer\Encoder\JsonEncoder;
  12. use Symfony\Contracts\Cache\ItemInterface;
  13. use Symfony\Contracts\Cache\CacheInterface;
  14. use App\Repository\ProjectRepository;
  15. use App\Repository\RedirectRepository;
  16. use App\Repository\DomainRepository;
  17. use App\Repository\HttpsTypeRepository;
  18. use App\Repository\BackendRepository;
  19. use App\Repository\NginxTemplateRepository;
  20. use App\Entity\Project;
  21. use App\Entity\Redirect;
  22. use Doctrine\ORM\EntityManagerInterface;
  23. use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
  24. use App\Form\Type\RedirectType;
  25. use App\Form\Type\ProjectType;
  26. use App\Entity\Ftp;
  27. class AdminController extends AbstractController
  28. {
  29. private $cache;
  30. private $repository;
  31. private $redirectsRepository;
  32. private $domainsRepository;
  33. private $https_repository;
  34. private $backend_repository;
  35. private $nginx_template_repository;
  36. private $manager;
  37. public function __construct(CacheInterface $cache, ProjectRepository $repository, RedirectRepository $redirectsRepository, DomainRepository $domainsRepository, HttpsTypeRepository $https_repository, BackendRepository $backend_repository, NginxTemplateRepository $nginx_template_repository, EntityManagerInterface $manager)
  38. {
  39. $this->cache = $cache;
  40. $this->repository = $repository;
  41. $this->redirectsRepository = $redirectsRepository;
  42. $this->domainsRepository = $domainsRepository;
  43. $this->https_repository = $https_repository;
  44. $this->backend_repository = $backend_repository;
  45. $this->nginx_template_repository = $nginx_template_repository;
  46. $this->manager = $manager;
  47. }
  48. /**
  49. * @Route("/", name="admin")
  50. */
  51. public function index()
  52. {
  53. $soft = $this->cache->get('versions', function (ItemInterface $item) {
  54. $item->expiresAfter(604800);
  55. return $this->getVersions();
  56. });
  57. return $this->render('admin/index.html.twig', [
  58. 'controller_name' => 'AdminController',
  59. 'soft' => $soft
  60. ]);
  61. }
  62. private function getVersions()
  63. {
  64. //skip versions check before multicore support
  65. return [];
  66. $process = Process::fromShellCommandline('sudo /webcrate/versions.py');
  67. $process->run();
  68. if (!$process->isSuccessful()) {
  69. throw new ProcessFailedException($process);
  70. }
  71. $soft_json = $process->getOutput();
  72. $encoder = new JsonEncoder();
  73. $soft = [];
  74. if(!empty($soft_json))
  75. {
  76. $soft = $encoder->decode($soft_json, 'json');
  77. }
  78. return $soft;
  79. }
  80. /**
  81. * @Route("/admin/projects", name="admin-projects")
  82. */
  83. public function projects()
  84. {
  85. $list = $this->repository->getListForTable();
  86. return $this->render('admin/projects.html.twig', [
  87. 'controller_name' => 'AdminController',
  88. 'projects' => $list,
  89. ]);
  90. }
  91. /**
  92. * @Route("/admin/redirects", name="admin-redirects")
  93. */
  94. public function redirects()
  95. {
  96. $list = $this->redirectsRepository->getListForTable();
  97. return $this->render('admin/redirects.html.twig', [
  98. 'controller_name' => 'AdminController',
  99. 'redirects' => $list,
  100. ]);
  101. }
  102. /**
  103. * @Route("/admin/domains", name="admin-domains")
  104. */
  105. public function domains()
  106. {
  107. $list = $this->domainsRepository->getListForTable();
  108. return $this->render('admin/domains.html.twig', [
  109. 'controller_name' => 'AdminController',
  110. 'domains' => $list,
  111. ]);
  112. }
  113. /**
  114. * @Route("/admin/project/add", name="project-add")
  115. */
  116. public function newProject(Request $request)
  117. {
  118. $project = new Project();
  119. $form = $this->createForm(ProjectType::class, $project);
  120. if ($request->isMethod('POST'))
  121. {
  122. $form->handleRequest($request);
  123. if ($form->isSubmitted() && $form->isValid())
  124. {
  125. $project = $form->getData();
  126. $project->setUid($this->repository->getFirstAvailableUid());
  127. $ftps = $project->getFtps();
  128. foreach ( $ftps as $ftp ) {
  129. $ftp->setProject($project);
  130. }
  131. $this->manager->persist($project);
  132. $this->manager->flush();
  133. $this->updateProjectsYaml();
  134. return $this->redirectToRoute('admin-projects');
  135. }
  136. }
  137. return $this->render(
  138. 'admin/project.html.twig',
  139. [
  140. 'form' => $form->createView(),
  141. ]
  142. );
  143. }
  144. /**
  145. * @Route("/admin/project/{uid}", name="admin-project")
  146. */
  147. public function project($uid, Request $request)
  148. {
  149. $project = $this->repository->loadByUid($uid);
  150. $form = $this->createForm(ProjectType::class, $project);
  151. if ($request->isMethod('POST'))
  152. {
  153. $form->handleRequest($request);
  154. if ($form->isSubmitted() && $form->isValid())
  155. {
  156. $project = $form->getData();
  157. $ftps = $project->getFtps();
  158. foreach ( $ftps as $ftp ) {
  159. $ftp->setProject($project);
  160. }
  161. $this->manager->persist($project);
  162. $this->manager->flush();
  163. $this->updateProjectsYaml();
  164. return $this->redirectToRoute('admin-projects');
  165. }
  166. }
  167. return $this->render(
  168. 'admin/project.html.twig',
  169. [
  170. 'form' => $form->createView()
  171. ]
  172. );
  173. }
  174. /**
  175. * @Route("/admin/project/{uid}/delete", name="admin-project-delete")
  176. */
  177. public function projectDelete($uid)
  178. {
  179. $project = $this->repository->loadByUid($uid);
  180. $this->manager->remove($project);
  181. $this->manager->flush();
  182. $list = $this->repository->getListForTable();
  183. $this->updateProjectsYaml();
  184. $response = new JsonResponse();
  185. $response->setData([
  186. 'result' => 'ok',
  187. 'projects' => $list
  188. ]);
  189. return $response;
  190. }
  191. /**
  192. * @Route("/admin/project/{uid}/activate", name="admin-project-activate")
  193. */
  194. public function projectActivate($uid)
  195. {
  196. $project = $this->repository->loadByUid($uid);
  197. $project->setActive(true);
  198. $this->manager->flush();
  199. $list = $this->repository->getListForTable();
  200. $this->updateProjectsYaml();
  201. $response = new JsonResponse();
  202. $response->setData([
  203. 'result' => 'ok',
  204. 'projects' => $list
  205. ]);
  206. return $response;
  207. }
  208. /**
  209. * @Route("/admin/project/{uid}/reload", name="admin-project-reload")
  210. */
  211. public function projectReload($uid)
  212. {
  213. $project = $this->repository->loadByUid($uid);
  214. if ( !$project->isActual() ) {
  215. try {
  216. $name = $project->getName();
  217. $process = Process::fromShellCommandline("sudo /webcrate/reload.py $name");
  218. $process->run();
  219. if (!$process->isSuccessful()) {
  220. throw new ProcessFailedException($process);
  221. }
  222. } catch (IOExceptionInterface $exception) {
  223. $debug['error'] = $exception->getMessage();
  224. }
  225. }
  226. $list = $this->repository->getListForTable();
  227. $response = new JsonResponse();
  228. $response->setData([
  229. 'result' => 'ok',
  230. 'projects' => $list
  231. ]);
  232. return $response;
  233. }
  234. /**
  235. * @Route("/admin/reload-config", name="admin-reload-config")
  236. */
  237. public function projectReloadConfig()
  238. {
  239. try {
  240. $process = Process::fromShellCommandline('sudo /webcrate/reload.py');
  241. $process->run();
  242. if (!$process->isSuccessful()) {
  243. throw new ProcessFailedException($process);
  244. }
  245. } catch (IOExceptionInterface $exception) {
  246. $debug['error'] = $exception->getMessage();
  247. }
  248. $response = new JsonResponse();
  249. $response->setData([
  250. 'result' => 'ok',
  251. ]);
  252. return $response;
  253. }
  254. /**
  255. * @Route("/admin/project/{uid}/deactivate", name="admin-project-deactivate")
  256. */
  257. public function projectDeactivate($uid)
  258. {
  259. $project = $this->repository->loadByUid($uid);
  260. $project->setActive(false);
  261. $this->manager->flush();
  262. $list = $this->repository->getListForTable();
  263. $this->updateProjectsYaml();
  264. $response = new JsonResponse();
  265. $response->setData([
  266. 'result' => 'ok',
  267. 'projects' => $list
  268. ]);
  269. return $response;
  270. }
  271. /**
  272. * @Route("/admin/import-projects", name="import-projects")
  273. */
  274. public function importProjects(Request $request): Response
  275. {
  276. $file = $request->files->get('file');
  277. $filepath = $file['tmp_name'];
  278. $projects = Yaml::parseFile($filepath);
  279. foreach ( $projects as $projectname => $project_obj ) {
  280. $project_obj = (object)$project_obj;
  281. $entity = $this->repository->loadByUid($project_obj->uid);
  282. if ( empty($entity) ) {
  283. $project = new Project();
  284. $project_obj->active = !empty($project_obj->active) ? $project_obj->active : false;
  285. $project_obj->memcached = !empty($project_obj->memcached) ? $project_obj->memcached : false;
  286. $project_obj->redis = !empty($project_obj->redis) ? $project_obj->redis : false;
  287. $project_obj->solr = !empty($project_obj->solr) ? $project_obj->solr : false;
  288. $project_obj->elastic = !empty($project_obj->elastic) ? $project_obj->elastic : false;
  289. $project_obj->redirect = !empty($project_obj->redirect) ? $project_obj->redirect : false;
  290. $project_obj->backup = !empty($project_obj->backup) ? $project_obj->backup : false;
  291. $project_obj->gzip = !empty($project_obj->gzip) ? $project_obj->gzip : false;
  292. $project_obj->mysql_db = !empty($project_obj->mysql_db) ? $project_obj->mysql_db : false;
  293. $project_obj->mysql5_db = !empty($project_obj->mysql5_db) ? $project_obj->mysql5_db : false;
  294. $project_obj->postgresql_db = !empty($project_obj->postgresql_db) ? $project_obj->postgresql_db : false;
  295. $project_obj->root_folder = !empty($project_obj->root_folder) ? $project_obj->root_folder : 'data';
  296. $project_obj->password = !empty($project_obj->password) ? $project_obj->password : 'empty_password';
  297. $project_obj->https = !empty($project_obj->https) ? $project_obj->https : 'disabled';
  298. $project_obj->backend = !empty($project_obj->backend) ? $project_obj->backend : 'php';
  299. $project_obj->backend_version = !empty($project_obj->backend_version) ? $project_obj->backend_version : '81';
  300. $project_obj->gunicorn_app_module = !empty($project_obj->gunicorn_app_module) ? $project_obj->gunicorn_app_module : '';
  301. $project_obj->nginx_template = !empty($project_obj->nginx_template) ? $project_obj->nginx_template : 'default';
  302. $project_obj->volume = !empty($project_obj->volume) ? $project_obj->volume : 0;
  303. $project_obj->nginx_block = !empty($project_obj->nginx_block) ? $project_obj->nginx_block : '';
  304. $project_obj->domains = !empty($project_obj->domains) ? $project_obj->domains : [$projectname . '.test'];
  305. $project_obj->nginx_options = !empty($project_obj->nginx_options) ? $project_obj->nginx_options : [];
  306. $project_obj->auth_locations = !empty($project_obj->auth_locations) ? $project_obj->auth_locations : [];
  307. $project_obj->duplicity_filters = !empty($project_obj->duplicity_filters) ? $project_obj->duplicity_filters : [];
  308. $project_obj->ftps = !empty($project_obj->ftps) ? $project_obj->ftps : [];
  309. $project_obj->ip_address = !empty($project_obj->ip_address) ? $project_obj->ip_address : '';
  310. $project->setUid($project_obj->uid);
  311. $project->setName($projectname);
  312. $project->setVolume($project_obj->volume);
  313. $project->setActive($project_obj->active == 'yes' || $project_obj->active === true);
  314. $project->setMemcached($project_obj->memcached == 'yes' || $project_obj->memcached === true);
  315. $project->setRedis($project_obj->redis == 'yes' || $project_obj->redis === true);
  316. $project->setSolr($project_obj->solr == 'yes' || $project_obj->solr === true);
  317. $project->setElastic($project_obj->elastic == 'yes' || $project_obj->elastic === true);
  318. $project->setBackup($project_obj->backup == 'yes' || $project_obj->backup === true);
  319. $project->setRedirect($project_obj->redirect == 'yes' || $project_obj->redirect === true);
  320. $project->setGzip($project_obj->gzip == 'yes' || $project_obj->gzip === true);
  321. $project->setMysql($project_obj->mysql_db == 'yes' || $project_obj->mysql_db === true);
  322. $project->setMysql5($project_obj->mysql5_db == 'yes' || $project_obj->mysql5_db === true);
  323. $project->setPostgre($project_obj->postgresql_db == 'yes' || $project_obj->postgresql_db === true);
  324. $project->setRootFolder($project_obj->root_folder);
  325. $project->setPasswordHash($project_obj->password);
  326. $project->setIpAddress($project_obj->ip_address);
  327. $https = $this->https_repository->findByName($project_obj->https);
  328. $project->setHttps($https);
  329. $backend_version = empty($project_obj->backend_version) ? ( $project_obj->backend == 'php' ? '81' : 'latest' ) : $project_obj->backend_version;
  330. $backend = $this->backend_repository->findByNameAndVersion($project_obj->backend, (string)$backend_version);
  331. $project->setBackend($backend);
  332. if ( !empty($project_obj->gunicorn_app_module) && ( $project_obj->backend == 'gunicorn' ) ) {
  333. $project->setGunicornAppModule($project_obj->gunicorn_app_module);
  334. }
  335. $template = $this->nginx_template_repository->findByName($project_obj->nginx_template);
  336. $project->setNginxTemplate($template);
  337. $project->setNginxBlock($project_obj->nginx_block);
  338. $project->setDomains($project_obj->domains);
  339. $options_array = [];
  340. foreach ( $project_obj->nginx_options as $name => $value ) {
  341. $options_array[] = [ 'name' => $name, 'value' => $value ];
  342. }
  343. $project->setNginxOptions($options_array);
  344. $locations_array = [];
  345. foreach ( $project_obj->auth_locations as $location ) {
  346. $locations_array[] = [
  347. 'path' => $location['path'],
  348. 'title' => $location['title'],
  349. 'user' => $location['user'],
  350. 'password' => $location['password']
  351. ];
  352. }
  353. $project->setAuthLocations($locations_array, true);
  354. $duplicity_filters_array = [];
  355. foreach ( $project_obj->duplicity_filters as $filter ) {
  356. $duplicity_filters_array[] = [
  357. 'mode' => $filter['mode'],
  358. 'path' => $filter['path']
  359. ];
  360. }
  361. $project->setDuplicityFilters($duplicity_filters_array, true);
  362. foreach ( $project_obj->ftps as $index => $ftp_data ) {
  363. $ftp = new Ftp();
  364. $ftp->setName($ftp_data['name']);
  365. $ftp->setWeight($index);
  366. $ftp->setPasswordHash($ftp_data['password']);
  367. $ftp->setHome($ftp_data['home']);
  368. $project->addFtp($ftp);
  369. }
  370. $this->manager->persist($project);
  371. }
  372. }
  373. $this->manager->flush();
  374. $this->updateProjectsYaml();
  375. $list = $this->repository->getListForTable();
  376. $response = new JsonResponse();
  377. $response->setData([
  378. 'result' => 'ok',
  379. 'projects' => $list
  380. ]);
  381. return $response;
  382. }
  383. public function updateProjectsYaml()
  384. {
  385. $ymlData = $this->getYmlData();
  386. try {
  387. $new_file_path = "/webcrate/updated-projects.yml";
  388. file_put_contents($new_file_path, $ymlData);
  389. $process = Process::fromShellCommandline('sudo /webcrate/updateprojects.py');
  390. $process->run();
  391. if (!$process->isSuccessful()) {
  392. throw new ProcessFailedException($process);
  393. }
  394. } catch (IOExceptionInterface $exception) {
  395. $debug['error'] = $exception->getMessage();
  396. }
  397. }
  398. public function getYmlData()
  399. {
  400. $projects = $this->repository->getList();
  401. $projects_list = (object)[];
  402. foreach ( $projects as $project ) {
  403. $projectname = $project->getName();
  404. $projects_list->$projectname = $project->toObject();
  405. }
  406. $ymlData = Yaml::dump($projects_list, 3, 2, Yaml::DUMP_OBJECT_AS_MAP);
  407. return $ymlData;
  408. }
  409. /**
  410. * @Route("/admin/redirect/add", name="redirect-add")
  411. */
  412. public function newRedirect(Request $request)
  413. {
  414. $redirect = new Redirect();
  415. $form = $this->createForm(RedirectType::class, $redirect);
  416. if ($request->isMethod('POST'))
  417. {
  418. $form->handleRequest($request);
  419. if ($form->isSubmitted() && $form->isValid())
  420. {
  421. $redirect = $form->getData();
  422. $this->manager->persist($redirect);
  423. $this->manager->flush();
  424. $this->updateRedirectsYaml();
  425. return $this->redirectToRoute('admin-redirects');
  426. }
  427. }
  428. return $this->render(
  429. 'admin/redirect.html.twig',
  430. [
  431. 'form' => $form->createView()
  432. ]
  433. );
  434. }
  435. /**
  436. * @Route("/admin/redirect/{name}", name="admin-redirect")
  437. */
  438. public function adminRedirect($name, Request $request)
  439. {
  440. $redirect = $this->redirectsRepository->loadByName($name);
  441. $form = $this->createForm(RedirectType::class, $redirect);
  442. if ($request->isMethod('POST'))
  443. {
  444. $form->handleRequest($request);
  445. if ($form->isSubmitted() && $form->isValid())
  446. {
  447. $redirect = $form->getData();
  448. $this->manager->persist($redirect);
  449. $this->manager->flush();
  450. $this->updateRedirectsYaml();
  451. return $this->redirectToRoute('admin-redirects');
  452. }
  453. }
  454. return $this->render(
  455. 'admin/redirect.html.twig',
  456. [
  457. 'form' => $form->createView()
  458. ]
  459. );
  460. }
  461. /**
  462. * @Route("/admin/redirect/{name}/delete", name="admin-redirect-delete")
  463. */
  464. public function redirectDelete($name)
  465. {
  466. $redirect = $this->redirectsRepository->loadByName($name);
  467. $this->manager->remove($redirect);
  468. $this->manager->flush();
  469. $list = $this->redirectsRepository->getListForTable();
  470. $this->updateRedirectsYaml();
  471. $response = new JsonResponse();
  472. $response->setData([
  473. 'result' => 'ok',
  474. 'redirects' => $list
  475. ]);
  476. return $response;
  477. }
  478. /**
  479. * @Route("/admin/redirect/{name}/activate", name="admin-redirect-activate")
  480. */
  481. public function redirectActivate($name)
  482. {
  483. $redirect = $this->redirectsRepository->loadByName($name);
  484. $redirect->setActive(true);
  485. $this->manager->flush();
  486. $list = $this->redirectsRepository->getListForTable();
  487. $this->updateRedirectsYaml();
  488. $response = new JsonResponse();
  489. $response->setData([
  490. 'result' => 'ok',
  491. 'redirects' => $list
  492. ]);
  493. return $response;
  494. }
  495. /**
  496. * @Route("/admin/redirect/{name}/reload", name="admin-redirect-reload")
  497. */
  498. public function redirectReload($name)
  499. {
  500. $redirect = $this->redirectsRepository->loadByName($name);
  501. if ( !$redirect->isActual() ) {
  502. try {
  503. $name = $redirect->getName();
  504. $process = Process::fromShellCommandline("sudo /webcrate/reload-redirect.py $name");
  505. $process->run();
  506. if (!$process->isSuccessful()) {
  507. throw new ProcessFailedException($process);
  508. }
  509. } catch (IOExceptionInterface $exception) {
  510. $debug['error'] = $exception->getMessage();
  511. }
  512. }
  513. $list = $this->redirectsRepository->getListForTable();
  514. $response = new JsonResponse();
  515. $response->setData([
  516. 'result' => 'ok',
  517. 'redirects' => $list
  518. ]);
  519. return $response;
  520. }
  521. /**
  522. * @Route("/admin/reload-redirect-config", name="admin-reload-redirect-config")
  523. */
  524. public function redirectReloadConfig()
  525. {
  526. try {
  527. $process = Process::fromShellCommandline('sudo /webcrate/reload-redirect.py');
  528. $process->run();
  529. if (!$process->isSuccessful()) {
  530. throw new ProcessFailedException($process);
  531. }
  532. } catch (IOExceptionInterface $exception) {
  533. $debug['error'] = $exception->getMessage();
  534. }
  535. $response = new JsonResponse();
  536. $response->setData([
  537. 'result' => 'ok'
  538. ]);
  539. return $response;
  540. }
  541. /**
  542. * @Route("/admin/redirect/{name}/deactivate", name="admin-redirect-deactivate")
  543. */
  544. public function redirectDeactivate($name)
  545. {
  546. $redirect = $this->redirectsRepository->loadByName($name);
  547. $redirect->setActive(false);
  548. $this->manager->flush();
  549. $list = $this->redirectsRepository->getListForTable();
  550. $this->updateRedirectsYaml();
  551. $response = new JsonResponse();
  552. $response->setData([
  553. 'result' => 'ok',
  554. 'redirects' => $list
  555. ]);
  556. return $response;
  557. }
  558. /**
  559. * @Route("/admin/import-redirects", name="import-redirects")
  560. */
  561. public function importRedirects(Request $request): Response
  562. {
  563. $file = $request->files->get('file');
  564. $filepath = $file['tmp_name'];
  565. $redirects = Yaml::parseFile($filepath);
  566. foreach ( $redirects as $redirectname => $redirect_obj ) {
  567. $redirect_obj = (object)$redirect_obj;
  568. $entity = $this->redirectsRepository->loadByName($redirectname);
  569. if ( empty($entity) ) {
  570. $redirect = new Redirect();
  571. $redirect_obj->active = !empty($redirect_obj->active) ? $redirect_obj->active : false;
  572. $redirect_obj->https = !empty($redirect_obj->https) ? $redirect_obj->https : 'disabled';
  573. $redirect_obj->domains = !empty($redirect_obj->domains) ? $redirect_obj->domains : [$redirectname . '.test'];
  574. $redirect->setActive($redirect_obj->active == 'yes' || $redirect_obj->active === true);
  575. $redirect->setName($redirectname);
  576. $redirect->setUrl($redirect_obj->url);
  577. $https = $this->https_repository->findByName($redirect_obj->https);
  578. $redirect->setHttps($https);
  579. $redirect->setDomains($redirect_obj->domains);
  580. $this->manager->persist($redirect);
  581. }
  582. }
  583. $this->manager->flush();
  584. $this->updateRedirectsYaml();
  585. $list = $this->redirectsRepository->getListForTable();
  586. $response = new JsonResponse();
  587. $response->setData([
  588. 'result' => 'ok',
  589. 'redirects' => $list
  590. ]);
  591. return $response;
  592. }
  593. public function updateRedirectsYaml()
  594. {
  595. $ymlData = $this->getRedirectsYmlData();
  596. try {
  597. $new_file_path = "/webcrate/updated-redirects.yml";
  598. file_put_contents($new_file_path, $ymlData);
  599. $process = Process::fromShellCommandline('sudo /webcrate/updateredirects.py');
  600. $process->run();
  601. if (!$process->isSuccessful()) {
  602. throw new ProcessFailedException($process);
  603. }
  604. } catch (IOExceptionInterface $exception) {
  605. $debug['error'] = $exception->getMessage();
  606. }
  607. }
  608. public function getRedirectsYmlData()
  609. {
  610. $redirects = $this->redirectsRepository->getList();
  611. $redirects_list = (object)[];
  612. foreach ( $redirects as $redirect ) {
  613. $redirectname = $redirect->getName();
  614. $redirects_list->$redirectname = $redirect->toObject();
  615. }
  616. $ymlData = Yaml::dump($redirects_list, 3, 2, Yaml::DUMP_OBJECT_AS_MAP);
  617. return $ymlData;
  618. }
  619. }