Config.pm 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package Trog::Config;
  2. use 5.040;
  3. use re '/aasx';
  4. use warnings FATAL => 'all';
  5. use FindBin::libs;
  6. use Config::Simple;
  7. =head1 Trog::Config
  8. A thin wrapper around Config::Simple which reads the configuration from the appropriate place.
  9. =head2 Trog::Config::get() = Config::Simple
  10. Returns a configuration object that will be used by server.psgi, the data model and Routing modules.
  11. Memoized, so you will need to HUP the children on config changes.
  12. Reads $home_cfg, falling back to $default when the instance has never saved a
  13. configuration of its own. Both are full paths relative to the tCMS root, so
  14. that writers can use them too -- an earlier version had the 'config/' prefix
  15. hardcoded here and nowhere else, which meant everything that *wrote* the
  16. configuration put it somewhere get() would never look.
  17. =cut
  18. # Where an instance's own configuration lives, once it has saved one.
  19. our $home_cfg = "config/main.cfg";
  20. # Shipped defaults. Tracked in git -- never write to this.
  21. our $default = "config/default.cfg";
  22. sub get {
  23. state $cf;
  24. return $cf if $cf;
  25. foreach my $cfg2try ( $home_cfg, $default ) {
  26. next unless -f $cfg2try; ## no critic (ProhibitFiletest_f) -- the instance config, else the shipped default
  27. $cf = Config::Simple->new($cfg2try);
  28. last;
  29. }
  30. die "Could not find config file!" unless $cf;
  31. return $cf;
  32. }
  33. =head2 Trog::Config::schema( STRING file = $default ) = ARRAYREF
  34. The shape of the configuration, as described by the file we ship.
  35. config/default.cfg is the only place which says what settings exist at all, so
  36. it is also what the /config editor is built out of -- add a key there and it
  37. becomes editable, leave one out and it isn't. Sections and keys come back in
  38. file order:
  39. [
  40. {
  41. section => 'general',
  42. fields => [
  43. {
  44. key => 'data_model',
  45. name => 'general.data_model',
  46. default => 'SQLite',
  47. comment => 'FlatFile or SQLite. ...',
  48. },
  49. ],
  50. },
  51. ]
  52. Comment lines accumulate until a key claims them, so a comment block is the
  53. help text for whatever setting follows it. Config::Simple throws both comments
  54. and ordering away when it reads a file, which is why this reads it again rather
  55. than asking the object we already have.
  56. Keys appearing before any section header are skipped -- Config::Simple has no
  57. name for them, so neither do we.
  58. =cut
  59. sub schema ( $file = $default ) {
  60. open( my $fh, '<', $file ) or die "Could not read $file: $!";
  61. my ( @sections, $section, @comments );
  62. while ( my $line = readline($fh) ) {
  63. chomp $line;
  64. $line =~ s/^\s+//;
  65. $line =~ s/\s+$//;
  66. next unless $line;
  67. if ( $line =~ m/^\[(\N+)\]$/ ) {
  68. $section = { section => $1, fields => [] };
  69. push( @sections, $section );
  70. @comments = ();
  71. next;
  72. }
  73. if ( $line =~ m/^[#;]\s?(\N*)$/ ) {
  74. push( @comments, $1 );
  75. next;
  76. }
  77. my ( $key, $value ) = $line =~ m/^([^=]+?)\s*=\s*(\N*)$/;
  78. next unless defined $key;
  79. next unless $section;
  80. push(
  81. @{ $section->{fields} },
  82. {
  83. key => $key,
  84. name => "$section->{section}.$key",
  85. default => $value,
  86. comment => join( ' ', @comments ),
  87. }
  88. );
  89. @comments = ();
  90. }
  91. close($fh);
  92. return \@sections;
  93. }
  94. 1;