Update.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <?php
  2. /**
  3. * TLDDatabase: Abstraction for Public Suffix List in PHP.
  4. *
  5. * @link https://github.com/layershifter/TLDDatabase
  6. *
  7. * @copyright Copyright (c) 2016, Alexander Fedyashov
  8. * @license https://raw.githubusercontent.com/layershifter/TLDDatabase/master/LICENSE Apache 2.0 License
  9. */
  10. namespace LayerShifter\TLDDatabase;
  11. use LayerShifter\TLDDatabase\Exceptions\IOException;
  12. use LayerShifter\TLDDatabase\Exceptions\UpdateException;
  13. use LayerShifter\TLDDatabase\Http\AdapterInterface;
  14. use LayerShifter\TLDDatabase\Http\CurlAdapter;
  15. /**
  16. * Class that performs database update with actual data from Public Suffix List.
  17. */
  18. class Update
  19. {
  20. /**
  21. * @const string URL to Public Suffix List file.
  22. * @todo Switch back after https://github.com/publicsuffix/list/issues/724 will be resolved
  23. */
  24. const PUBLIC_SUFFIX_LIST_URL = 'https://raw.githubusercontent.com/publicsuffix/list/master/public_suffix_list.dat';
  25. /**
  26. * @var AdapterInterface Object of HTTP adapter.
  27. */
  28. private $httpAdapter;
  29. /**
  30. * @var string Output filename.
  31. */
  32. private $outputFileName;
  33. /**
  34. * Parser constructor.
  35. *
  36. * @param string $outputFileName Filename of target file
  37. * @param string $httpAdapter Optional class name of custom HTTP adapter
  38. *
  39. * @throws UpdateException
  40. */
  41. public function __construct($outputFileName = null, $httpAdapter = null)
  42. {
  43. /*
  44. * Defining output filename.
  45. * */
  46. $this->outputFileName = null === $outputFileName
  47. ? __DIR__ . Store::DATABASE_FILE
  48. : $outputFileName;
  49. /*
  50. * Defining HTTP adapter.
  51. * */
  52. if (null === $httpAdapter) {
  53. $this->httpAdapter = new CurlAdapter();
  54. return;
  55. }
  56. if (!class_exists($httpAdapter)) {
  57. throw new Exceptions\UpdateException(sprintf('Class "%s" is not defined', $httpAdapter));
  58. }
  59. $this->httpAdapter = new $httpAdapter();
  60. if (!($this->httpAdapter instanceof AdapterInterface)) {
  61. throw new Exceptions\UpdateException(sprintf('Class "%s" is implements adapter interface', $httpAdapter));
  62. }
  63. }
  64. /**
  65. * Fetches actual Public Suffix List and writes obtained suffixes to target file.
  66. *
  67. * @return void
  68. *
  69. * @throws IOException
  70. */
  71. public function run()
  72. {
  73. /*
  74. * Fetching Public Suffix List and parse suffixes.
  75. * */
  76. $lines = $this->httpAdapter->get(Update::PUBLIC_SUFFIX_LIST_URL);
  77. $parser = new Parser($lines);
  78. $suffixes = $parser->parse();
  79. /*
  80. * Write file with exclusive file write lock.
  81. * */
  82. $handle = @fopen($this->outputFileName, 'w+');
  83. if ($handle === false) {
  84. throw new Exceptions\IOException(error_get_last()['message']);
  85. }
  86. if (!flock($handle, LOCK_EX)) {
  87. throw new Exceptions\IOException(sprintf('Cannot obtain lock to output file (%s)', $this->outputFileName));
  88. }
  89. $suffixFile = '<?php' . PHP_EOL . 'return ' . var_export($suffixes, true) . ';';
  90. $writtenBytes = fwrite($handle, $suffixFile);
  91. if ($writtenBytes === false || $writtenBytes !== strlen($suffixFile)) {
  92. throw new Exceptions\IOException(sprintf('Write to output file (%s) failed', $this->outputFileName));
  93. }
  94. flock($handle, LOCK_UN);
  95. fclose($handle);
  96. }
  97. }