package Mojolicious::Che; use Mojo::Base::Che; # 郋迡邽郇 郈訄��� 迡郅�� �訄郱郋赲 use Mojo::Base 'Mojolicious'; use Mojo::Log::Che; use Mojo::Loader qw(load_class); #~ use Mojo::Util qw(url_unescape); #~ use Scalar::Util 'weaken'; sub new { my ($class, %args) = @_; my $config = delete($args{config}) || 'Config.pm'; my $app = $class->SUPER::new(%args); $app->plugin(Config =>{file => $config}); #~ return $app # 郋��訄郇郋赲郕訄 邽郅邽 迡赲郋邿郇郋邿 郈迮�迮郱訄郈��郕 kill -USR2 #~ if $ENV{HYPNOTOAD_PID} || $ENV{HYPNOTOAD_STOP}; my $conf = $app->config; $conf->{mojo} ||= {}; my $defaults = $conf->{'mojo_defaults'} || $conf->{'mojo'}{'defaults'} || $conf->{'mojo.defaults'}; $app->defaults($defaults) if $defaults; my $secret = $conf->{'mojo_secret'} || $conf->{'mojo_secrets'} || $conf->{'mojo'}{'secret'} || $conf->{'mojo'}{'secrets'} || $conf->{'mojo.secret'} || $conf->{'mojo.secrets'} || $conf->{'��解����'} || [rand]; $app->secrets($secret); my $mode = $conf->{'mojo_mode'} || $conf->{'mojo'}{'mode'} || $conf->{'mojo.mode'}; $app->mode($mode) # 苳訄邿郅 郅郋迣訄 �迠迮 郇迮 郈迮�迮郕郅�耯箮解�� if $mode; #~ $app->log->level( $conf->{'mojo_log_level'} || $conf->{'mojo'}{'log_level'} || 'debug'); my $log = $conf->{'mojo_log'} || $conf->{'mojo.log'} || $conf->{'mojo'}{'log'}; $app->log(Mojo::Log::Che->new(%$log)) if $log; #~ warn "Mode: ", $app->mode, "; log level: ", $app->log->level; my $home = $app->home; my $statics = $conf->{'mojo_static_paths'} || $conf->{'mojo.static.paths'} || $conf->{'mojo'}{'static'}{'paths'} || []; #~ push @{$app->static->paths}, @{$paths} if $paths; push @{$app->static->paths}, $home->rel_file($_) for @$statics; my $templates_paths = $conf->{'mojo_renderer_paths'} || $conf->{'mojo.renderer.paths'} || $conf->{'mojo'}{'renderer'}{'paths'} || []; push @{$app->renderer->paths}, $home->rel_dir($_) for @$templates_paths; my $renderer_classes = $conf->{'mojo_renderer_classes'} || $conf->{'mojo.renderer.classes'} || $conf->{'mojo'}{'renderer'}{'classes'} || []; push @{$app->renderer->classes}, $_ for grep ! load_class($_), @$renderer_classes; $app->�迮��邽��(); $app->�訄郱��(); #~ $app->訇訄郱��(); #~ $app->郱訄郈�郋���(); $app->郈郅�迣邽郇��(); $app->��郕邽(); $app->�郈迮邿���(); $app->邾訄��������(); $app->郱訄迡訄�箮�(); $app->�邽郈��(); #~ $app->minion_worker(); return $app; } sub �訄郱�� { # 苭訄郱�� 邽郱 郕郋郇�邽迣訄 my $app = shift; my $conf = $app->config; my $h = $conf->{'mojo_has'} || $conf->{'mojo.has'} || $conf->{'mojo'}{'has'} || $conf->{'�訄郱��'}; map { $app->log->debug("Make the app->has('$_')"); has $_ => $h->{$_}; } keys %$h; } #~ sub 郈郅�迣邽郇�� {# �氱銑�迣邽郇�� 邽郱 郕郋郇�邽迣訄 has 郈郅�迣邽郇�� => sub { my $app = shift; my $conf = $app->config; my $郈郅�迣邽郇�� = {}; my $plugins = $conf->{'mojo_plugins'} || $conf->{'mojo.plugins'} || $conf->{'mojo'}{'plugins'} || $conf->{'郈郅�迣邽郇��'} || return; map { push @{ $郈郅�迣邽郇��->{$_->[0]} ||= [] }, [ref $_->[1] eq 'CODE' ? $app->plugin($_->[0] => $app->${ \$_->[1] }) : $app->plugin(@$_)]; $app->log->debug("Enable plugin [$_->[0]]"); } @$plugins; return $郈郅�迣邽郇��; }; has dbh => sub { #~ sub 訇訄郱�� {# 郋訇�訄訇訄��氵紹匾萃� dbh 郕郋郇�邽迣訄 my $app = shift; my $conf = $app->config; my $c_dbh = $conf->{dbh} || $conf->{'訇訄郱��'}; return unless $c_dbh && ref($c_dbh) eq 'HASH' && keys %$c_dbh; #~ has dbh => sub {{};} #~ unless $app->can('dbh'); my $dbh = {}; my $req_dbi; while (my ($db, $opt) = each %$c_dbh) { if ($opt->{dbh}) {# && ref $opt eq 'DBI::db' $dbh->{$db} ||= $opt->{dbh}; } else { ++$req_dbi and require DBI unless $req_dbi; $dbh->{$db} ||= DBI->connect(@{$opt->{connect}}); $app->log->debug("苤郋迮迡邽郇邽郅��� � 訇訄郱郋邿 $opt->{connect}[0] app->dbh->{'$db'}"); } map { $dbh->{$db}->do($_); } @{$opt->{do}} if $opt->{do}; } return $dbh; }; has sth => sub { #~ sub 郱訄郈�郋��� {# 郋訇�訄訇訄��氵紹匾萃� sth 郕郋郇�邽迣訄 my $app = shift; my $dbh = eval { $app->dbh } or return; #~ my %arg = @_; my $conf = $app->config; my $c_dbh = $conf->{dbh} || $conf->{'訇訄郱��'}; my $c_sth = $conf->{sth} || $conf->{'郱訄郈�郋���'} || {}; #~ my $c_pos = $conf->{pos} || $conf->{'郈郋���'} || {}; return unless ($c_sth && ref($c_sth) eq 'HASH' && keys %$c_sth); #~ || ($c_pos && ref($c_pos) eq 'HASH' && keys %$c_pos); my $sth = {}; while (my ($db, $opt) = each %$c_dbh) { while (my ($st, $sql) = each %{$opt->{sth}}) { $sth->{$db}{$st} = $dbh->{$db}->prepare($sql);# $app->sth->{main}{...} $app->log->debug("�氱憶棣創憾�郋赲邽郅��� 郱訄郈�郋� [app->sth->{$db}{$st}]"); } } while (my ($db, $h) = each %$c_sth) { while (my ($st, $sql) = each %$h) { $sth->{$db}{$st} = $dbh->{$db}->prepare($sql);# $app->sth->{main}{...} $app->log->debug("�氱憶棣創憾�郋赲邽郅��� 郱訄郈�郋� [app->sth->{$db}{$st}]"); } } $sth; }; sub ��郕邽 {# 苭�郕邽 邽郱 郕郋郇�邽迣訄 my $app = shift; my $conf = $app->config; my $hooks = $conf->{'mojo_hooks'} || $conf->{'mojo.hooks'} || $conf->{'mojo'}{'hooks'} || $conf->{'��郕邽'} || return; while (my ($name, $sub) = each %$hooks) { if (ref $sub eq 'ARRAY') { $app->hook($name => $_) for @$sub; } else { $app->hook($name => $sub); } $app->log->debug(sprintf("Applied hook%s [%s] from config", ref $sub eq 'ARRAY' ? "s (@{[ scalar @$sub]})" : '', $name)); } } sub �迮��邽�� { my $app = shift; my $conf = $app->config; my $session = $conf->{'mojo_session'} || $conf->{'mojo_sessions'} || $conf->{'mojo.session'} || $conf->{'mojo.sessions'} || $conf->{'mojo'}{'session'} || $conf->{'mojo'}{'sessions'} || $conf->{'�迮��邽邽'} || $conf->{'�迮��邽��'} || return; #~ $app->sessions->cookie_name($session->{'cookie_name'}) #~ if $session->{'cookie_name'}; #~ $app->sessions->default_expiration($session->{'default_expiration'}) # set expiry #~ if defined $session->{'default_expiration'}; while (my ($meth, $val) = each %$session) { next unless $app->sessions->can($meth); $app->sessions->$meth($val); } } sub 邾訄�������� { my $app = shift; my $conf = $app->config; my $routes = $conf->{'mojo_routes'} || $conf->{'mojo.routes'} || $conf->{'mojo'}{'routes'} || $conf->{'routes'} || $conf->{'邾訄��������'} or return; my $app_routes = $app->routes; my $apply_route = sub { my $r = shift || $app_routes; my ($meth, $arg) = @_; my $nr; if (my $m = $r->can($meth)) { $nr = $r->$m($arg) unless ref($arg); $nr = $r->$m(cb => $arg) if ref($arg) eq 'CODE'; $nr = $r->$m(@$arg) if ref($arg) eq 'ARRAY'; $nr = $r->$m(%$arg) if ref($arg) eq 'HASH'; } else { $app->log->warn("Can't method [$meth] for route",); } return $nr; }; for my $r (@$routes) { my $nr = $apply_route->($app_routes, @$r[0,1]) or next; $app->log->debug("Apply route [$r->[0] $r->[1]]"); for( my $i = 2; $i < @$r; $i += 2 ) { $nr = $apply_route->($nr, @$r[$i, $i+1]) or next; } } } sub �郈迮邿��� { my $app = shift; my $conf = $app->config; my $ns = $conf->{'mojo_namespaces'} || $conf->{'mojo.namespaces'} || $conf->{'mojo'}{'namespaces'} || $conf->{'namespaces'} || $conf->{'ns'} || $conf->{'�郈迮邿���'} || return; push @{$app->routes->namespaces}, @$ns; } sub 郱訄迡訄�箮� { my $app = shift; my $conf = $app->config; my $tasks = $conf->{'jobs'} || $conf->{'tasks'} || $conf->{'郱訄迡訄�箮�'} or return; die "You have jobs and first enable plugin Minion" unless $app->renderer->get_helper('minion'); while (my ($name, $sub) = each %$tasks) { $app->log->debug(sprintf("Applied task [%s] in [%s] from config", $name, $app->minion->add_task($name => $sub))); } #~ $app->minion->reset; } sub �邽郈�� {#MIME my $app = shift; my $conf = $app->config; my $types = $conf->{'mojo_types'} || $conf->{'mojo.types'} || $conf->{'mojo'}{'types'} || $conf->{'types'} || $conf->{'�邽郈��'} or return; while (my ($name, $val) = each %$types) { $app->types->type($name => $val); $app->log->debug(sprintf("Applied type [%s] from config", $name)); } } # overide only on my $path = $req->url->path->to_abs_string; sub Mojolicious::dispatch { my ($self, $c) = @_; my $plugins = $self->plugins->emit_hook(before_dispatch => $c); # Try to find a static file my $tx = $c->tx; $self->static->dispatch($c) and $plugins->emit_hook(after_static => $c) unless $tx->res->code; # Start timer (ignore static files) my $stash = $c->stash; $self->log->debug(sub { my $req = $c->req; my $url = $req->url->to_abs; $c->helpers->timing->begin('mojo.timer'); return sprintf qq{[%s] %s "%s://%s%s%s"}, $req->request_id, $req->method, $url->scheme, $url->host, $url->port ? ":".$url->port : '', $url->path->to_route; }) unless $stash->{'mojo.static'}; # Routes $plugins->emit_hook(before_routes => $c); $c->helpers->reply->not_found unless $tx->res->code || $self->routes->dispatch($c) || $tx->res->code; } our $VERSION = '0.0824';# as to Mojolicious/100+0.000<minor> =pod =encoding utf8 =head1 Mojolicious::Che �秴憶敗�郋迣郋 赲�迮邾 癒 癒 癒 ALL GLORY TO GLORIA ! ! ! =head1 VERSION 0.0824 =head1 NAME Mojolicious::Che - �婧憶� 訇訄郱郋赲�氵� 邾郋迡�郅�� 迡郅�� 郈�邽郅郋迠迮郇邽邿 Mojolicious. �罉�迠迮郇 �郋郅�芿碟� �訄郱赲迮�郇���氵� 郕郋郇�邽迣. =head1 SYNOPSIS # app.pl use lib 'lib'; use Mojo::Base 'Mojolicious::Che'; __PACKAGE__->new(config => 'lib/Config.pm')->start(); =head1 Config file �氱憾��觧棣憶� ���郋郕 赲 �殁�郋邾 郕郋郇�邽迣迮 �郋郋�赲迮���赲�迮� 邽�郈郋郅郇迮郇邽�� 赲 邾郋迡�郅迮! { '�𠇲�郋迮郕�'=>'苠迮��-郈�郋迮郕�', # mojo => { # defaults => # secrets => # mode=> # log => {level=>...} # static => {paths => [...]}, # renderer => {paths => [...], classes => [...], }, # session[s] => # has => # plugins => # hooks => # namespaces => # routes => # jobs => # types => # }, # or with prefix mojo_ # Default values for "stash" in Mojolicious::Controller, assigned for every new request. mojo_defaults => {layout=>'default',}, # '��解����' => [ mojo_secrets => ['true 123 my app',], mojo_mode=> 'development', mojo_log=>{level => 'error'}, mojo_static_paths => ["static"], mojo_renderer_classes => ["Mojolicious::Foo::Fun"], # '�迮��邽��'(邽郅邽 �迮��邽邽) => mojo_session[s] => {cookie_name => 'EXX', default_expiration => 86400}, # '�訄郱��' => '�𠝹萃� 500-700 郇訄郱訄迡 訇�氵� �訄郕郋邿 迡邽郕邽邿 ��迮郈郇郋邿 �郋�迣郋赲�氵� 迠訄迡郇�氵� 郇訄�郋迡 苭�𡤕灧𡤕㘵�. 苤�郋郅邽�迮邿 邽� "迣郋��迡訄���赲訄" 訇�氵� 迣郋�郋迡 苠�芿槽��訄�訄郕訄郇��, 迣迡迮-�郋 郇訄 訇迮�迮迣� 邾郋��� �惧參�郈邽��. �氱憾�郋邾郕邽 �殁�邽� 郅�耨棣菩� �訄���氵諱匾諸� 郈郋 ���訄郇訄邾 �㘵憾��邽邽, 苤�迮迡郇迮邿 �𡤕煩覜�, �𢌡紼�郋郈��. �䢛���� 邾郇迮郇邽迮, �𢒼�郋 �訄郱訄��� 郈�邽�赲郋邽郅邽 �迮訇迮 郇訄郱赲訄郇邽迮 �𢌡𠸝㘵𢌡�, 郇郋 �殁�郋 郇迮 �迮 訇邽訇郅迮邿�郕邽迮 郕�郋�郕邽迮 迮赲�迮邽, 訄 迠訄迡郇�氵� 郈郋�郋邾郕邽 郕�郋邾訄郇�芿憶諸�迮赲' mojo_has => { foo => sub {my $app = shift; return 'is a bar';}, }, # '訇訄郱��' => # will be as has! dbh=>{ 'main' => { # DBI->connect(dsn, user, passwd, $attrs) connect => ["DBI:Pg:dbname=test;", "postgres", undef, { ShowErrorStatement => 1, AutoCommit => 1, RaiseError => 1, PrintError => 1, pg_enable_utf8 => 1, #mysql_enable_utf8 => 1, #mysql_auto_reconnect=>1, }], # or use Foo::Dbh; external defined dbh # dbh => Dbh->dbh, # will do on connect do => ['set datestyle to "ISO, DMY";',], # prepared sth will be as has $app->sth->{<dbh name>}{<sth name>} sth => { foo => <<SQL, select * from foo where bar = ?; SQL }, } }, # '郱訄郈�郋���' => # prepared sth will be as has $app->sth->{<dbh name>}{<sth name>} sth => { main => { now => "select now();" }, }, # '郈郅�迣邽郇��'=> [ mojo_plugins=>[ ['Foo::Bar'], [Foo::Bar::Plugin => opt1 => ..., opt2 => ...], ['Foo::Plugin' => sub {<...returns config data list...>}], ], # '��郕邽' => mojo_hooks=>{ #~ before_dispatch => sub {1;}, }, # '�郈迮邿���' => [...] namespaces => ['Space::Shattle'], # '邾訄��������' => [...] routes => [ [get=>'/', to=> {cb=>sub{shift->render(format=>'txt', text=>'Hello friend!');},}], ] #~ '郱訄迡訄�箮�'=> {#first enable plugin Minion jobs => { slow_log => sub { my ($job, $msg) = @_; sleep 5; $job->app->log->error(qq{slow_log "$msg"}); }, }, # 邽郅邽 '�邽郈��'=>{...} types => { docx => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'], ... }, }; =head1 ATTRIBUTES B<Mojolicious::Che> inherits all attributes from L<Mojolicious> and implements the following new ones. =head2 dbh Set DBI handlers from config B<dbh> (邽郅邽 B<訇訄郱��>) my $dbh = $app->dbh->{main}; =head2 sth Set prepared stattements from config B<sth> (邽郅邽 B<郱訄郈�郋���>). my $sth = $app->sth->{main}{foo}; =head2 郈郅�迣邽郇�� Apply the plugins. See L<Mojolicious#plugins>, L<Mojolicious::Plugins>. =head1 METHODS B<Mojolicious::Che> inherits all methods from L<Mojolicious> and implements the following new ones. =head2 �迮��邽��() Session object config apply. See L<Mojolicious#sessions>, L<Mojolicious::Sessions>. =head2 �訄郱��() Apply the has's. UTF names allow. =head2 ��郕邽() Apply the hooks. See L<Mojolicious#HOOKS>. =head2 �郈迮邿���() Apply the namespaces. Push @{$app->routes->namespaces} your namespaces. See L<Mojolicious#routes>. namespaces => ['Space::Shattle'], =head2 邾訄��������() Apply the routes. See L<Mojolicious#routes>, L<Mojolicious::Guides::Routing>. #~ '邾訄��������' => [ 'routes'=>[ [get=>'/', to=> {cb=>sub{shift->render(format=>'txt', text=>'Welcome!');},}], ], =head2 郱訄迡訄�箮�() Apply the jobs. See L<Minion>. #~ '郱訄迡訄�箮�'=> {#first enable plugin Minion 'jobs'=> { # or tasks slow_log => sub { my ($job, $msg) = @_; sleep 5; $job->app->log->error(qq{slow_log "$msg"}); }, }, =head �邽郈��() Apply the new types. See L<Mojolicious#types>, L<Mojolicious::Types>. =head1 SEE ALSO L<Mojolicious> L<Ado> =head1 AUTHOR �婧解�訄邽郅 虴迮 (Mikhail Che), C<< <mche[-at-]cpan.org> >> =head1 BUGS / CONTRIBUTING Please report any bugs or feature requests at L<https://github.com/mche/Mojolicious-Che/issues>. Pull requests also welcome. =head1 COPYRIGHT Copyright 2016+ Mikhail Che. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1;