File Coverage

blib/lib/Nile/File.pm
Criterion Covered Total %
statement 29 177 16.3
branch 10 60 16.6
condition 1 26 3.8
subroutine 9 48 18.7
pod 0 39 0.0
total 49 350 14.0


line stmt bran cond sub pod time code
1             # Copyright Infomation
2             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3             # Author : Dr. Ahmed Amin Elsheshtawy, Ph.D.
4             # Website: https://github.com/mewsoft/Nile, http://www.mewsoft.com
5             # Email : mewsoft@cpan.org, support@mewsoft.com
6             # Copyrights (c) 2014-2015 Mewsoft Corp. All rights reserved.
7             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8             package Nile::File;
9              
10             our $VERSION = '0.54';
11             our $AUTHORITY = 'cpan:MEWSOFT';
12              
13             =pod
14              
15             =encoding utf8
16              
17             =head1 NAME
18              
19             Nile::File - Files and folders manager.
20              
21             =head1 SYNOPSIS
22            
23             # get app context
24             $app = $self->app;
25              
26             # get the file content as a single string.
27             $content = $app->file->get($file);
28              
29             # get the file content as an array of lines.
30             @lines = $app->file->get($file);
31            
32             # get list of specific files in a folder
33             @files = $app->file->files("c:/apache/htdocs/nile/", "*.pm, *.cgi");
34            
35             # get list of specific files in a folder recursively
36             # files_tree($dir, $match, $relative, $depth)
37             @files = $app->file->files_tree("c:/apache/htdocs/nile/", "*.pm, *.cgi");
38              
39             # get list of sub folders in a folder
40             #folders($dir, $match, $relative)
41             @folders = $self->file->folders("c:/apache/htdocs/nile/", "", 1);
42            
43             # get list of sub folders in a folder recursively
44             #folders_tree($dir, $match, $relative, $depth)
45             @folders = $self->file->folders_tree("c:/apache/htdocs/nile/", "", 1);
46              
47             =head1 DESCRIPTION
48              
49             The file object provides tools for reading files, folders, and most of the functions in the modules L<File::Spec> and L<File::Basename>.
50              
51             to get file content as single string or array of strings:
52            
53             $content = $app->file->get($file);
54             @lines = $app->file->get($file);
55              
56             supports options same as L<File::Slurp>.
57              
58             To get list of files in a specific folder:
59            
60             #files($dir, $match, $relative)
61             @files = $app->file->files("c:/apache/htdocs/nile/", "*.pm, *.cgi");
62            
63             #files_tree($dir, $match, $relative, $depth)
64             @files = $app->file->files_tree("c:/apache/htdocs/nile/", "*.pm, *.cgi");
65              
66             #folders($dir, $match, $relative)
67             @folders = $self->file->folders("c:/apache/htdocs/nile/", "", 1);
68              
69             #folders_tree($dir, $match, $relative, $depth)
70             @folders = $self->file->folders_tree("c:/apache/htdocs/nile/", "", 1);
71              
72             Nile::File - Files and folders manager.
73              
74             =cut
75              
76 1     1   4 use Nile::Base;
  1         2  
  1         6  
77 1     1   5511 use File::Slurp;
  1         3  
  1         65  
78 1     1   627 use File::Find::Rule;
  1         6647  
  1         7  
79 1     1   44 use File::Basename ();
  1         2  
  1         12  
80 1     1   4 use File::Temp ();
  1         1  
  1         15  
81 1     1   4 use IO::Compress::Gzip qw($GzipError);
  1         2  
  1         122  
82 1     1   600 use IO::Uncompress::Gunzip qw($GunzipError) ;
  1         11918  
  1         95  
83 1     1   649 use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
  1         38193  
  1         418  
84              
85             our ($OS, %DS, $DS);
86              
87             BEGIN {
88 1 50   1   6 unless ($OS = $^O) { require Config; eval(q[$OS=$Config::Config{osname}]) }
  0         0  
  0         0  
89 1 50       14 if ($OS =~ /^darwin/i) { $OS = 'UNIX';}
  0 50       0  
    50          
    50          
    50          
    50          
    50          
    50          
    50          
90 0         0 elsif ($OS =~ /^cygwin/i) { $OS = 'CYGWIN';}
91 0         0 elsif ($OS =~ /^MSWin/i) { $OS = 'WINDOWS';}
92 0         0 elsif ($OS =~ /^vms/i) { $OS = 'VMS';}
93 0         0 elsif ($OS =~ /^bsdos/i) { $OS = 'UNIX';}
94 0         0 elsif ($OS =~ /^dos/i) { $OS = 'DOS';}
95 0         0 elsif ($OS =~ /^MacOS/i) { $OS = 'MACINTOSH';}
96 0         0 elsif ($OS =~ /^epoc/) { $OS = 'EPOC';}
97 0         0 elsif ($OS =~ /^os2/i) { $OS = 'OS2';}
98 1         2 else { $OS = 'UNIX';}
99              
100 1         7 %DS = ('DOS' => '\\', 'EPOC' => '/', 'MACINTOSH' => ':',
101             'OS2' => '\\', 'UNIX' => '/', 'WINDOWS' => chr(92),
102             'VMS' => '/', 'CYGWIN' => '/');
103 1   50     2079 $DS = $DS{$OS} || '/';
104             }
105              
106             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
107             =head2 get()
108            
109             # file($file, $options)
110             $content = $app->file->get("/path/file.txt");
111             @lines = $app->file->get("/path/file.txt");
112              
113             $bin = $app->file->get("/path/file.bin", binmode => ':raw');
114             $utf = $app->file->get("/path/file.txt", binmode => ':utf8');
115              
116             Reads file contents into a single variable or an array. This method is a wrapper around L<File::Slurp> read_file method.
117              
118             =cut
119              
120             sub get {
121             #shift if ref ($_[0]) || $_[0] eq __PACKAGE__;
122 0     0 0   my $self = shift;
123 0           my $file = shift ;
124 0 0         my $opts = (ref $_[0] eq 'HASH' ) ? shift : {@_};
125            
126             # if wantarray, default to chomp lines
127             #if (defined wantarray && ! exists $opts->{chomp}) {
128             # $opts->{chomp} = 1;
129             #}
130              
131             #my $bin_data = read_file( $bin_file, binmode => ':raw' );
132             #my $utf_text = read_file( $bin_file, binmode => ':utf8' ); chomp=>1
133 0           return read_file($file, $opts);
134             }
135             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
136             =head2 put()
137            
138             # put($file, $options)
139             $app->file->put($file, @data);
140             $app->file->put($file, {binmode => ':raw'}, $buffer);
141              
142             $app->file->put($file, \$buffer);
143             # the same as
144             $app->file->put($file, $buffer);
145              
146             $app->file->put($file, \@lines) ;
147             # the same as
148             $app->file->put($file, @lines) ;
149              
150             Writes contents into a file. This method is a wrapper around L<File::Slurp> write_file method.
151             The first argument is the filename. The second argument is an optional hash reference and it
152             contains key/values that can modify the behavior of write_file. The rest of the argument list is the data to be written to the file.
153              
154             =cut
155              
156             sub put {
157 0     0 0   my $self = shift;
158             #shift if ref ($_[0]) || $_[0] eq __PACKAGE__;
159             #write_file( $bin_file, {binmode => ':raw'}, @data );
160             #write_file( $bin_file, {binmode => ':utf8', append => 1}, $utf_text );
161 0           return write_file(@_);
162             }
163             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
164             =head2 File::Spec supported methods
165            
166             $app->file->canonpath;
167             $app->file->catdir
168             $app->file->catfile
169             $app->file->curdir
170             $app->file->rootdir
171             $app->file->updir
172             $app->file->no_upwards
173             $app->file->file_name_is_absolute
174             $app->file->path
175             $app->file->devnull
176             $app->file->tmpdir
177             $app->file->splitpath
178             $app->file->splitdir
179             $app->file->catpath
180             $app->file->abs2rel
181             $app->file->rel2abs
182             $app->file->case_tolerant
183              
184             Wrapper methods around L<File::Spec> functions.
185              
186             =cut
187              
188 0     0 0   sub canonpath {shift; File::Spec->canonpath(@_);}
  0            
189 0     0 0   sub catdir {shift; File::Spec->catdir(@_);}
  0            
190 0     0 0   sub catfile {shift; File::Spec->catfile(@_);}
  0            
191 0     0 0   sub curdir {shift; File::Spec->curdir(@_);}
  0            
192 0     0 0   sub rootdir {shift; File::Spec->rootdir(@_);}
  0            
193 0     0 0   sub updir {shift; File::Spec->updir(@_);}
  0            
194 0     0 0   sub no_upwards {shift; File::Spec->no_upwards(@_);}
  0            
195 0     0 0   sub file_name_is_absolute {shift; File::Spec->file_name_is_absolute(@_);}
  0            
196 0     0 0   sub path {shift; File::Spec->path(@_);}
  0            
197 0     0 0   sub devnull {shift; File::Spec->devnull(@_);}
  0            
198 0     0 0   sub tmpdir {shift; File::Spec->tmpdir(@_);}
  0            
199 0     0 0   sub splitpath {shift; File::Spec->splitpath(@_);}
  0            
200 0     0 0   sub splitdir {shift; File::Spec->splitdir(@_);}
  0            
201 0     0 0   sub catpath {shift; File::Spec->catpath(@_);}
  0            
202 0     0 0   sub abs2rel {shift; File::Spec->abs2rel(@_);}
  0            
203 0     0 0   sub rel2abs {shift; File::Spec->rel2abs(@_);}
  0            
204 0     0 0   sub case_tolerant {shift; File::Spec->case_tolerant(@_);}
  0            
205             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
206             =head2 files()
207            
208             # files($dir, $match, $relative)
209             @files = $app->file->files("c:/apache/htdocs/nile/", "*.pm, *.cgi");
210              
211             Returns a list of files in a specific folder. The first argument is the path, the second argument is the filename match
212             if not set will match all files, the third argument is the relative flag, if set will include the relative path of the files.
213              
214             =cut
215              
216             sub files {
217 0     0 0   my ($self, $dir, $match, $relative) = @_;
218 0           $relative += 0;
219             #($dir, $match, $depth, $folders, $relative)
220 0           return $self->scan_dir($dir, $match, 1, 0, $relative);
221             }
222             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
223             =head2 files_tree()
224            
225             # files_tree($dir, $match, $relative, $depth)
226             @files = $app->file->files_tree("c:/apache/htdocs/nile/", "*.pm, *.cgi");
227              
228             Returns a list of files in a specific folder. The first argument is the path, the second argument is the filename match
229             if not set will match all files, the third argument is the relative flag, if set will include the relative path of the files.
230              
231             =cut
232              
233             sub files_tree {
234 0     0 0   my ($self, $dir, $match, $relative, $depth) = @_;
235             #($dir, $match, $depth, $folders, $relative)
236 0           return $self->scan_dir($dir, $match, $depth, 0, $relative);
237             }
238             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
239             =head2 folders()
240            
241             # get list of sub folders in a folder
242             # folders($dir, $match, $relative)
243             @folders = $self->file->folders("c:/apache/htdocs/nile/", "", 1);
244            
245             # get list of sub folders in a folder recursively
246             #folders_tree($dir, $match, $relative, $depth)
247             @folders = $self->file->$folders_tree("c:/apache/htdocs/nile/", "", 1);
248              
249             Returns a list of sub folders in a folder.
250              
251             =cut
252              
253             sub folders {
254 0     0 0   my ($self, $dir, $match, $relative) = @_;
255 0           return $self->scan_dir($dir, $match, 1, 1, $relative);
256             }
257             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
258             =head2 folders_tree()
259            
260             # get list of sub folders in a folder recursively
261             #folders_tree($dir, $match, $relative, $depth)
262             @folders = $self->file->folders_tree("c:/apache/htdocs/nile/", "", 1);
263              
264             Returns list of sub folders in a folder recursively.
265              
266             =cut
267              
268             sub folders_tree {
269 0     0 0   my ($self, $dir, $match, $relative, $depth) = @_;
270 0           return $self->scan_dir($dir, $match, $depth, 1, $relative);
271             }
272             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
273             sub scan_dir {
274 0     0 0   my ($self, $dir, $match, $depth, $folders, $relative) = @_;
275 0           my ($rule, @match);
276            
277 0   0       $dir ||= "";
278 0   0       $match ||= "";
279 0           $depth += 0;
280            
281             #$relative != $relative;
282             #$relative = ($relative)? 0 : 1;
283            
284             #my @files = File::Find::Rule->file->name( "*.pm" )->maxdepth( $depth )->in( $dir );
285             #my @subdirs = File::Find::Rule->directory->maxdepth( 1 )->relative->in( "." );
286              
287 0           $rule = File::Find::Rule->new();
288              
289 0 0         if ($folders) {
290 0           $rule->directory();
291             }
292             else {
293 0           $rule->file();
294             }
295              
296 0 0         if ($relative) {$rule->relative();}
  0            
297              
298 0 0         if ($match) {
299 0           @match = split(/\s*\,\s*/, $match); # *.cgi, *.pm, *.ini, File::Find::Rule->name( '*.avi', '*.mov' ),
300 0           $rule->name(@match);
301             }
302            
303             # depth=0 for unlimited depth recurse
304 0 0         if ($depth) {$rule->maxdepth($depth);}
  0            
305            
306 0 0         if (ref($dir) eq 'ARRAY' ) {
307 0           @$dir = map {$self->catdir($_)} @$dir;
  0            
308 0           return ($rule->in(@$dir));
309             }
310             else {
311 0           return ($rule->in($self->catdir($dir)));
312             }
313             }
314             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
315             =head2 os()
316            
317             my $os = $app->file->os;
318              
319             Returns the name of the operating system.
320              
321             =cut
322              
323 0     0 0   sub os {$OS}
324              
325             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
326             =head2 ds()
327            
328             my $ds = $app->file->ds;
329              
330             Returns the directory separator of the operating system.
331              
332             =cut
333              
334 0     0 0   sub ds {$DS}
335             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
336             =head2 fileparse()
337            
338             my ($filename, $dirs, $suffix) = $app->file->fileparse($path);
339             my ($filename, $dirs, $suffix) = $app->file->fileparse($path, @suffixes);
340             my $filename = $app->file->fileparse($path, @suffixes);
341              
342             Splits a file path into its $dirs, $filename and (optionally) the filename $suffix. See L<File::Basename>
343              
344             =cut
345              
346             sub fileparse {
347 0     0 0   my ($self) = shift;
348 0           return File::Basename::fileparse(@_);
349             }
350             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
351             =head2 basename()
352            
353             my $filename = $app->file->basename($path);
354             my $filename = $app->file->basename($path, @suffixes);
355              
356             Returns the last level of a filepath even if the last level is clearly directory. In effect, it is acting like pop() for paths. See L<File::Basename>
357              
358             =cut
359              
360             sub basename {
361 0     0 0   my ($self) = shift;
362 0           return File::Basename::basename(@_);
363             }
364             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
365             =head2 dirname()
366            
367             my $ds = $app->file->dirname();
368              
369             Returns the directory separator of the operating system. See L<File::Basename>
370              
371             =cut
372              
373             sub dirname {
374 0     0 0   my ($self) = shift;
375 0           return File::Basename::dirname(@_);
376             }
377             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
378             =head2 path_info()
379            
380             my ($name, $dir, $ext, $name_ext) = $app->file->path_info($path);
381              
382             Splits a file path into its $dir, $name, filename $suffix, and name with suffix.
383              
384             =cut
385              
386             sub path_info {
387 0     0 0   my ($self, $path) = @_;
388 0           my ($name, $dir, $ext) = File::Basename::fileparse($path, qr/\.[^.]*/); # qr/\.[^.]*/ matched against the end of the $filename.
389 0           return ($name, $dir, $ext, $name.$ext);
390             }
391             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
392             =head2 open()
393            
394             $fh = $app->file->open($file);
395             $fh = $app->file->open($mode, $file);
396             $fh = $app->file->open($mode, $file, $charset);
397             $fh = $app->file->open(">", $file, "utf8");
398              
399             Open file and returns a filehandle.
400              
401             =cut
402              
403             sub open {
404            
405 0     0 0   my $self = shift;
406 0           my ($mode, $filename, $charset);
407              
408 0 0         if (@_ == 1) {
    0          
    0          
409 0           ($filename) = @_;
410 0           $charset = "";
411             }
412             elsif (@_ == 2) {
413 0           ($mode, $filename) = @_;
414 0           $charset = "";
415             }
416             elsif (@_ == 3) {
417 0           ($mode, $filename, $charset) = @_;
418             }
419            
420 0   0       $mode ||= "<";
421 0 0         CORE::open(my $fh, $mode, $filename) or $self->app->abort("Error opening file $filename in mode $mode. $!");
422 0 0         binmode $fh, ":encoding($charset)" if ($charset);
423 0           return $fh;
424             }
425             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
426             =head2 tempfile()
427            
428             #$template = "tmpdirXXXXXX";
429             ($fh, $filename) = $app->file->tempfile($template);
430             ($fh, $filename) = $app->file->tempfile($template, DIR => $dir);
431             ($fh, $filename) = $app->file->tempfile($template, SUFFIX => '.dat');
432             ($fh, $filename) = $app->file->tempfile($template, TMPDIR => 1 );
433              
434             Return name and handle of a temporary file safely. This is a wrapper for the L<File::Temp> tempfile function.
435              
436             =cut
437              
438             sub tempfile {
439 0     0 0   my $self = shift;
440             #(TEMPLATE => 'tempXXXXX', DIR => 'mydir', SUFFIX => '.dat', TMPDIR => 1)
441 0           my ($fh, $filename) = File::Temp::tempfile(@_);
442             #binmode $fh, ":encoding($charset)";
443 0           binmode($fh, ":utf8");
444 0           return ($fh, $filename);
445             }
446             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
447             =head2 tempdir()
448            
449             $tmpdir = $app->file->tempdir($template);
450             $tmpdir = $app->file->tempdir($template, DIR => $dir);
451             $tmpdir = $app->file->tempdir($template, TMPDIR => 1 );
452              
453             Return name of a temporary directory safely. This is a wrapper for the L<File::Temp> tempdir function.
454              
455             =cut
456              
457             sub tempdir {
458 0     0 0   my $self = shift;
459             #(TEMPLATE => 'tempXXXXX', DIR => 'mydir', CLEANUP => 1, TMPDIR => 1)
460 0 0         if (@_ == 1) {
461 0           return File::Temp::tempdir(shift, TMPDIR => 1, CLEANUP => 1);
462             }
463             else {
464 0           return File::Temp::tempdir(@_);
465             }
466             }
467             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
468             =head2 gzip()
469            
470             $file = "file.txt";
471             $app->file->gzip($file);
472             # creates file.txt.gz
473            
474             $input = "file.txt";
475             $output = "file.gz";
476             $app->file->gzip($input, $output);
477             # creates file.gz
478            
479             # rename file in gzip header to file1.txt
480             $app->file->gzip($input, $output, "file1.txt");
481              
482             Compress and create gzip files from input files.
483              
484             =cut
485              
486             sub gzip {
487 0     0 0   my ($self, $input, $output, $outname) = @_;
488 0   0       $output ||= "$input.gz";
489 0           my ($name, $dir, $ext, $filename) = $self->path_info($input);
490 0   0       $outname ||= $filename;
491 0 0         IO::Compress::Gzip::gzip $input => $output, Name => $outname or $self->app->abort("Gzip failed for $input => $output: $GzipError");
492             }
493             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
494             =head2 gunzip()
495            
496             $file = "file.txt";
497             $app->file->gzip($file);
498             # creates file.txt.gz
499            
500             $input = "file.txt";
501             $output = "file.gz";
502             $app->file->gzip($input, $output);
503             # creates file.gz
504            
505             # rename file in gzip header to file1.txt
506             $app->file->gzip($input, $output, "file1.txt");
507              
508             Extract gzip files.
509              
510             =cut
511              
512             sub gunzip {
513 0     0 0   my ($self, $input, $output) = @_;
514 0   0       $output ||= $input;
515 0           $output =~ s/\.gz//i ;
516 0 0         IO::Uncompress::Gunzip::gunzip $input => $output or $self->app->abort("Gunzip failed for $input => $output: $GunzipError");
517             }
518             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
519             =head2 zip()
520            
521             $file = "file.txt";
522             $app->file->zip($file);
523             # creates file.zip
524            
525             $input = "file.txt";
526             $output = "file1.zip";
527             $app->file->gzip($input, $output);
528             # creates file1.zip
529            
530             # rename file in zip header to file1.txt
531             $app->file->zip($input, $output, "file1.txt");
532              
533             Compress and create zip files from input files.
534              
535             =cut
536              
537             sub zip {
538 0     0 0   my ($self, $input, $output, $outname) = @_;
539 0 0         unless ($output) {
540 0           $output = $input;
541 0           $output =~ s/\.[^.]*$//;
542 0           $output .= ".zip";
543             }
544 0           my ($name, $dir, $ext, $filename) = $self->path_info($input);
545 0   0       $outname ||= $filename;
546 0           my $zip = Archive::Zip->new();
547 0           my $file_member = $zip->addFile($input, $outname);
548 0 0         unless ($zip->writeToFileNamed($output) == AZ_OK) {
549 0           $self->app->abort("Zip failed for $input => $output $!");
550             }
551             }
552             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
553             =head2 unzip()
554            
555             $file = "/path/file.zip";
556             $app->file->unzip($file);
557             # extracts files to /path/
558            
559             $app->file->unzip($file, $dest);
560             # extracts files to $dest
561            
562             Extract zip files.
563              
564             =cut
565              
566             sub unzip {
567 0     0 0   my ($self, $input, $dest) = @_;
568            
569 0           my $zip = Archive::Zip->new();
570              
571 0 0         unless ($zip->read($input) == AZ_OK) {
572 0           $self->app->abort("Unzip failed for $input $!");
573             }
574            
575 0 0         unless ($dest) {
576 0           my ($name, $dir, $ext, $filename) = $self->path_info($input);
577 0           $dest = $dir; # =~ s/[^\\\/]+$//;
578             }
579              
580             #$zip->extractTree($root, $dest, $volume);
581 0           $zip->extractTree("", $dest, "");
582             }
583             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
584             =head2 view()
585            
586             my $file = $app->file->view($view, $theme);
587              
588             # get view file name in the current theme
589             my $file = $app->file->view("home");
590             # /app/theme/default/view/home.html
591              
592             my $file = $app->file->view("home", "Arabic");
593             # /app/theme/Arabic/view/home.html
594              
595             Returns the full file path for a view name.
596              
597             =cut
598              
599             sub view {
600 0     0 0   my ($self, $view, $theme) = @_;
601 0 0         $view .= ".html" unless ($view =~ /\.html$/i);
602 0   0       $theme ||= $self->app->var->get("theme");
603 0           $self->app->file->catfile($self->app->var->get("themes_dir"), $theme, "view", $view);
604             }
605             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
606             =head2 lang()
607            
608             my $file = $app->file->lang($filename, $lang);
609              
610             # get language file pth in the current language
611             my $file = $app->file->lang("general");
612             # /app/lang/en-US/general.xml
613              
614             my $file = $app->file->lang("general", "ar");
615             # /app/lang/ar/general.xml
616              
617             Returns the full file path for a language file name.
618              
619             =cut
620              
621             sub lang {
622 0     0 0   my ($self, $file, $lang) = @_;
623 0   0       $lang ||= $self->app->var->get("lang");
624 0 0         $file .= ".xml" unless ($file =~ /\.xml$/i);
625 0           $self->app->file->catfile($self->app->var->get("langs_dir"), $lang, $file);
626             }
627             #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
628              
629             =pod
630              
631             =head1 Bugs
632              
633             This project is available on github at L<https://github.com/mewsoft/Nile>.
634              
635             =head1 HOMEPAGE
636              
637             Please visit the project's homepage at L<https://metacpan.org/release/Nile>.
638              
639             =head1 SOURCE
640              
641             Source repository is at L<https://github.com/mewsoft/Nile>.
642              
643             =head1 SEE ALSO
644              
645             See L<Nile> for details about the complete framework.
646              
647             =head1 AUTHOR
648              
649             Ahmed Amin Elsheshtawy, احمد امين الششتاوى <mewsoft@cpan.org>
650             Website: http://www.mewsoft.com
651              
652             =head1 COPYRIGHT AND LICENSE
653              
654             Copyright (C) 2014-2015 by Dr. Ahmed Amin Elsheshtawy احمد امين الششتاوى mewsoft@cpan.org, support@mewsoft.com,
655             L<https://github.com/mewsoft/Nile>, L<http://www.mewsoft.com>
656              
657             This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
658              
659             =cut
660              
661             1;