new \ZipArchive extension not working in Drupal module - drupal-8

Error: Class 'Drupal\checklist_download\Controller\ZipArchive' not found in Drupal\checklist_download\Controller\ChDownloadController->page() (line 42 of modules/checklist_download/src/Controller/ChDownloadController.php).
zip extension installed,
simple php file on domain working, but not in module
$zip = new \ZipArchive;
$zip->open($archive_name ,ZipArchive::CREATE|ZipArchive::OVERWRITE);
foreach ($b as $filename => $file) {
$zip->addFile($filename, $file);
}
$zip->close();

You can use Drupals own "ArchiverManager" for that:
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Archiver%21ArchiverManager.php/8.3.x
//Set path to zip-file or create empty Zip-file:
$zip_path =\Drupal::service('file_system')->saveData('','temporary://'.$zip_name.'.zip');
$zip = \Drupal::service('plugin.manager.archiver')->getInstance(['filepath' => $zip_path]);
foreach ($b as $filename => $filePath) {
$zip->add($filePath);
}

Related

Vtiger CRM #: How to write PHP code in log4php.properties file

I am new to Vtiger CRM. I want to write php code in log4php.properties file and also it need to be executed.
I can write the code but it is not executing at all. So kindly help me with a way which will allow to execute the file.
Also this need to be executed dynamic with separate domains.
Thanks
Open your index.php file from crm root directory and Add this code
function replace_string_in_a_file($filepath, $search, $replace) {
if (#file_exists($filepath)) {
$file = file($filepath);
foreach ($file as $index => $string) {
if (strpos($string, $search) !== FALSE)
$file[$index] = "$replace\n";
}
$content = implode($file);
return $content;
}else {
return NULL;
}
}
$filepath = $root_directory . 'log4php.properties';
$search = 'log4php.appender.A1.File=';
$replace = 'log4php.appender.A1.File=' . DOMAIN_PATH . '/logs/vtigercrm.log';
$log_properties_content = replace_string_in_a_file($filepath, $search, $replace);
if (!empty($log_properties_content)) {
file_put_contents($filepath, $log_properties_content);
}

Sending TWIG output to a zip in Symfony for Templating

I need to create a system that will be able to output a template (a zip with an index.html with all js, css, img etc files as required) based on a set of options (include menu 1, use small footer etc).
So I can put code blocks in so it would not be hard to actually output to the browser the required look, but what if I want to save the rendered html (and this means we would need to change the locations of files like js etc) to a zip instead?
Any ideas? At the moment I'm thinking it would all need to be processed in PHP anyhow (the controller) and TWIG may not be too helpful, but that would make it more complicated.
So I worked this one out, here is the controller to output the required twig zipped:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
/**
* #Route("/{variableName}", name="homepage"})
*/
public function indexAction($variableName = "Default")
{
//do whatever you need to get the template correct
//send rendered TWIG to a variable
$renderedhtml = $this->render('default/index.html.twig', [
'variableName' => $variableName
])->getContent();
$zipName = "template.zip";
$main = $this->get('kernel')->getRootDir() . '/../web/workingdir/';
$vername = time(); //we use the exact time to get a unique dir name
//remove any projects older than a few minutes (5 in this case)
$dirHandle = opendir($main);
while($item = readdir($dirHandle)){
if(is_dir($main . $item) && $item != '.' && $item != '..') {
if ( ( ( $item + ( 60 * 5 ) ) < $vername ) ) {
system('/bin/rm -rf ' . escapeshellarg($main . $item));
}
}
}
//make the project dir and populate it with files (in this case just the template as index.html, you would want to copy all other files here though)
mkdir($main.$vername);
file_put_contents($main.$vername."/index.html", $renderedhtml);
//create the zip
$zip = new \ZipArchive();
$zip->open($zipName, \ZipArchive::CREATE);
$zip = $this->createZip($zip, $main.$vername);
$zip->close();
//get the zip ready to return
header('Content-Type', 'application/zip');
header('Content-disposition: attachment; filename="' . $zipName . '"');
header('Content-Length: ' . filesize($zipName));
readfile($zipName);
}
// Create a zip with zip object and root dir params (find and include sub-dirs with content)
private function createZip($zip, $source) {
$source = str_replace('\\', '/', realpath($source));
if (is_dir($source) === true) {
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source), \RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file) {
$file = str_replace('\\', '/', $file);
if( in_array(substr($file, strrpos($file, '/')+1), array('.', '..')) )
continue;
$file = realpath($file);
if (is_dir($file) === true)
{
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
}
else if (is_file($file) === true)
{
$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
}
return $zip;
}
}
Once you get it to this stage, you will just have to add any other required files into the working dir, but I think that could be done under a different issue, this one is about getting the website into a html in a zip.
Hope this helps someone.

Perl: Splitting a variable containing a path to directory

So I'm having a problem trying to split a variable that has the complete path to a directory. I want to fetch the files under 'logs' directory of this path:
'/nfs/fm/disks/fm_mydiskhere_00000/users/me/repotest/myrepo/tools/toolsdir/logs/*';
and in my Perl script, I have a variable that contains this path: '$log_file'. When I print '$log_file', it contains the entire path; I want to go to the last directory 'logs' and fetch the files under it. By the way, this complete path is in a separate configuration file that is being read by my Perl script this way:
sub read_file {
my ($log_file) = shift(#_);
info ("Using file : $log_file");
my $fh = new FileHandle ("$log_file");
printError ("Could not open this file : '$log_file' - $!") unless defined $fh;
my $contents;
{
local $/ = undef;
$contents = <$fh>;
}
$fh->close();
eval $contents;
if ($#) {
chomp $#;
my $msg = "BAD (perl) syntax in file:\n\n$#\n";
if ( $msg =~ /requires explicit package name/ ) {
$msg .= "\n -> A 'requires explicit package name' message means".
" a NON-VALID variable name was found\n";
}
die "Error: $msg\n\n";
}
return 1;
}
And I'm using variable $log_file in another subroutine this way:
my $fh = read_file ($log_file);
if ($log_file eq "abc.txt"){
while (my $line = <$fh>) {
#do something
}
}
Can anybody help me here, please? Am I missing something or using $log_file in the wrong way?
Thanks in advance!
Try:
my #files = glob($log_file);
use Data::Dumper;
print Dumper(\#files);

Perl Regex Filename Not Matching

I'm running a Perl script that someone else wrote for me, and I've noticed that the following regex doesn't seem to match my files which are named "Film CD 1.avi", "Film2 CD 1.avi" etc:
$name = (split (/[ ]*CD[ ]*1/i, $in_avi))[0];
Anyone know what I need to do to correct it?
/Edit: The full code is this:
#!/usr/bin/perl
use strict;
########################################################################
# Configuration Details #
########################################################################
# Array of movies to convert
my #MOVIES_TO_CONVERT; # = ('The Figher', 'The Fifth Element');
# Directory where the split AVI files are stored
my $MOVIE_IN_PATH = 'D:\split';
# Directory where the combined AVI files will be stored
my $MOVIE_OUT_PATH = 'D:\combined';
# Full path to the avidemux executable
my $AVIDEMUX = 'C:\Program Files (x86)\Avidemux\avidemux.exe';
########################################################################
# Functions #
########################################################################
# Return an array of all the AVI files in the specified directory.
sub get_avis_in_directory
{
my $dh; # Directory handle
my $dir; # Current directory
my #avis; # Array of file names to return
opendir ($dh, $dir = shift) or die "Failed to open directory $dir: $!\n";
while (readdir $dh)
{
next if (/^\.{1,2}/);
$_ = $dir . "\\" . $_;
push (#avis, $_) if (-f $_ and /.*\.avi$/i);
}
closedir $dh;
return (#avis);
}
########################################################################
# Entry Point #
########################################################################
die "Input directory $MOVIE_IN_PATH does not exist!\n" unless (-d $MOVIE_IN_PATH);
die "Output directory $MOVIE_OUT_PATH does not exist!\n" unless (-d $MOVIE_OUT_PATH);
# This variable represents the actual names and paths of movies to be converted.
# It will either be built from the files specified in #MOVIES_TO_CONVERT manually, or
# built dynamically based on the files in the source and destination paths.
my #movies_formatted; # Array of hashes of movies to convert
if ($#MOVIES_TO_CONVERT == -1)
{
my #in_avis; # Array of AVI files in the input directory
my #out_avis; # Array of AVI files in the ouput directory
#in_avis = get_avis_in_directory ($MOVIE_IN_PATH);
#out_avis = get_avis_in_directory ($MOVIE_OUT_PATH);
for my $in_avi (#in_avis)
{
if ($in_avi =~ /.*[ ]*CD[ ]*1\.avi$/i)
{
my $rec; # Temporary hash variable
my $name; # Name of the move we are processing
$name = (split (/[ ]*CD[ ]*1/i, $in_avi))[0];
$name = (split (/$MOVIE_IN_PATH[\\\/]{1}/i, $name))[1];
for my $in_avi_2 (#in_avis)
{
if ($in_avi_2 =~ /^$MOVIE_IN_PATH\\$name[ ]*CD[ ]*2\.avi$/i)
{
$rec->{'part2'} = $in_avi_2;
last;
}
}
if (defined $rec->{'part2'})
{
for my $out_avi (#out_avis)
{
if ($out_avi =~ /$name\.avi$/i)
{
$rec->{'output'} = $out_avi;
last;
}
}
unless (defined $rec->{'output'})
{
$rec->{'part1'} = $in_avi;
$rec->{'output'} = "$MOVIE_OUT_PATH\\$name.avi";
push (#movies_formatted, $rec);
}
}
}
}
}
else
{
my $rec; # Temporary hash variable
for my $name (#MOVIES_TO_CONVERT)
{
$rec = {};
$rec->{'part1'} = "$MOVIE_IN_PATH\\$name CD 1.avi";
$rec->{'part2'} = "$MOVIE_IN_PATH\\$name CD 2.avi";
$rec->{'output'} = "$MOVIE_OUT_PATH\\$name.avi";
push (#movies_formatted, $rec);
}
}
for my $movie (#movies_formatted)
{
my $convert_cmd = "\"$AVIDEMUX\" --load \"" . $movie->{'part1'} . "\" --append \"" . $movie->{'part2'} . "\" --force-smart --save \"" . $movie->{'output'} . "\" --quit";
print "$convert_cmd\n";
die "Unable to convert $movie->{'output'}!\n" if (system "$convert_cmd");
}
Script from http://www.neowin.net/forum/topic/1128384-batch-file-to-run-command-on-joining-video-files by xorangekiller.
The backslash in $MOVIE_IN_PATH is being removed by interpolating it into the regular expression. Change both the split commands to
$name = (split(/\Q$MOVIE_IN_PATH\E[\\\/]{1}/i, $name))[1];
i.e. add the \Q ... \E to escape any regex metacharacters.
Your friend doesn't appear to be a particularly good Perl programmer. You may want to try this code instead.
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
use File::Spec;
# Configuration Details
#######################
# Array of movies to convert
my #MOVIES_TO_CONVERT; # = ('The Fighter', 'The Fifth Element');
# Directory where the split AVI files are stored
my $MOVIE_IN_PATH = 'D:\split';
# Directory where the combined AVI files will be stored
my $MOVIE_OUT_PATH = 'D:\combined';
# Full path to the avidemux executable
my $AVIDEMUX = 'C:\Program Files (x86)\Avidemux\avidemux.exe';
sub get_avis_in_directory {
opendir my $dh, $MOVIE_IN_PATH or die $!;
return grep {
/\.avi$/ and -f File::Spec->catfile($MOVIE_IN_PATH, $_)
} readdir $dh;
}
-d $MOVIE_IN_PATH or die qq(Input directory "$MOVIE_IN_PATH" does not exist!\n);
-d $MOVIE_OUT_PATH or die qq(Output directory "$MOVIE_OUT_PATH" does not exist!\n);
my #movies_formatted; # Array of hashes of movies to convert
if (#MOVIES_TO_CONVERT) {
for my $name (#MOVIES_TO_CONVERT) {
my $rec = {};
$rec->{part1} = File::Spec->catfile($MOVIE_IN_PATH, "$name CD 1.avi");
$rec->{part2} = File::Spec->catfile($MOVIE_IN_PATH, "$name CD 2.avi");
$rec->{output} = File::Spec->catfile($MOVIE_OUT_PATH, "$name.avi");
push #movies_formatted, $rec;
}
}
else {
my #in_avis = get_avis_in_directory($MOVIE_IN_PATH);
for my $in_avi (#in_avis) {
next unless $in_avi =~ /^(.+?)\s*CD\s*1\.avi$/i;
my $name = $1;
my $rec = {};
$rec->{part1} = $in_avi;
($rec->{part2}) = grep /^\Q$name\E\s*CD\s*2\.avi$/i, #in_avis;
if ($rec->{part2}) {
$rec->{$_} = File::Spec->catfile($MOVIE_IN_PATH, $rec->{$_}) for qw/ part1 part2 /;
$rec->{output} = File::Spec->catfile($MOVIE_OUT_PATH, "$name.avi");
push #movies_formatted, $rec;
}
}
}
for my $movie (#movies_formatted) {
my $convert_cmd = sprintf '"%s" --load "%s" --append "%s" --force-smart --save "%s" --quit',
$AVIDEMUX, #{$movie}{qw/ part1 part2 output /};
print "$convert_cmd\n";
die "Unable to convert $movie->{'output'}!\n" if (system $convert_cmd);
}
In what way doesn't it work?
use warnings;
use strict;
while (<DATA>) {
my $in_avi = $_;
my $name = (split (/[ ]*CD[ ]*1/i, $in_avi))[0];
print "$name\n";
}
__DATA__
Film CD 1.avi
Film2 CD 1.avi
Prints:
Film
Film2

Finding the last "}" of a subroutine

Supposed I have a file with Perl-code: does somebody know, if there is a module which could find the closing "}" of a certain subroutine in that file.
For example:
#!/usr/bin/env perl
use warnings;
use 5.012;
routine_one( '{°^°}' );
routine_two();
sub routine_one {
my $arg = shift;
if ( $arg =~ /}\z/ ) {
say "Hello my }";
}
}
sub routine_two {
say '...' for 0 .. 10
}
The module should be able to remove the whole routine_one or it should can tell me the line-number of the closing "}" from that routine.
You want to use PPI if you are going to be parsing Perl code.
#!/usr/bin/env perl
use warnings;
use 5.012;
use PPI;
my $file = 'Example.pm';
my $doc = PPI::Document->new( $file );
$doc->prune( 'PPI::Token::Pod' );
$doc->prune( 'PPI::Token::Comment' );
my $subs = $doc->find( sub { $_[1]->isa('PPI::Statement::Sub') and $_[1]->name eq 'layout' } );
die if #$subs != 1;
my $new = PPI::Document->new( \qq(sub layout {\n say "my new layout_code";\n}) );
my $subs_new = $new->find( sub { $_[1]->isa('PPI::Statement::Sub') and $_[1]->name eq 'layout' } );
$subs->[0]->block->insert_before( $subs_new->[0]->block ) or die $!;
$subs->[0]->block->remove or die $!;
# $subs->[0]->replace( $subs_new->[0] );
# The ->replace method has not yet been implemented at /usr/local/lib/perl5/site_perl/5.12.2/PPI/Element.pm line 743.
$doc->save( $file ) or die $!;
The following will work in case your subroutines don't contain any blank lines, like the one in your example:
#!/usr/bin/perl -w
use strict;
$^I = ".bkp"; # to create a backup file
{
local $/ = ""; # one paragraph constitutes one record
while (<>) {
unless (/^sub routine_one \{.+\}\s+$/s) { # 's' => '.' will also match "\n"
print;
}
}
}