File Coverage

blib/lib/Nile/File.pm
Criterion Covered Total %
statement 32 182 17.5
branch 10 62 16.1
condition 1 26 3.8
subroutine 10 49 20.4
pod 0 39 0.0
total 53 358 14.8


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