Sending TWIG output to a zip in Symfony for Templating - templates

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.

Related

Drupal 8 Webform add prefix to uploaded file names

I have a webform with a file upload field. I need do one of two things. Either upload files into a subfolder inside the private area, OR, add a prefix to the filename that the user is uploading. The user can upload several files. The webform editor allows you to 'Rename' the file and use tokens for this, but I don't see any way of preserving the original file name. I can hack getFileDestinationUri() in WebformManagedFileBase.php to do what I want, but obviously I would rather not do that. Am I missing something?
It turns out that you can use the drupal form alter hook to alter the destination. I had thought of this but felt if was unlikely to work. It does.
Below is MY code solution: (I may be missing container types)
function _mymodule_fix_elements(&$elements) {
foreach ($elements as $key => &$element) {
if (strpos($key, '#') !== 0) {
if (is_array($element)) {
if (isset($element['#type'])) {
if (($element['#type'] == 'fieldset') ||
($element['#type'] == 'webform_flexbox') ||
($element['#type'] == 'container')) {
_mymodule_fix_elements($element);
} else if ($element['#type'] == 'managed_file') {
$pattern = $element['#upload_location'];
if (strpos($pattern, 'private:') === 0) {
$element['#upload_location'] = $pattern . '/' . $key;
}
}
}
}
}
}
}
function mymodule_form_alter(&$form, &$form_state, $id) {
if (strpos($id, 'webform_') === 0) {
_mymodule_fix_elements($form['elements']);
}
}

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);
}

How to pass project number to manifest.json

I am building a web push WordPress plugin and I want to pass project number from form input field to manifest.json file
which is included in index.php as
<link rel="manifest" href="/manifest.json">
Disclaimer: I'm the author of this plugin.
Instead of building your own from scratch, you could contribute to the already existing https://github.com/mozilla/wp-web-push.
If you want to build your own, you can check the source of that plugin out to see how we have implemented it.
We've built a class to handle it: https://github.com/marco-c/wp-web-app-manifest-generator.
You cannot pass any param to the manifest.json. You must genarate it as a static file when the form is submitted.
Here's the code that we have used for the Pushpad plugin:
if (file_exists ( ABSPATH . 'manifest.json' )) {
$oldManifestJson = file_get_contents ( ABSPATH . 'manifest.json' );
} else {
$oldManifestJson = '{}';
}
$data = json_decode ( $oldManifestJson, true );
$data ['gcm_sender_id'] = $settings ['gcm_sender_id'];
$data ['gcm_user_visible_only'] = true;
$newManifestJson = json_encode ( $data );
if ( is_writable ( ABSPATH . 'manifest.json' ) || !file_exists ( ABSPATH . 'manifest.json' ) && is_writable ( ABSPATH ) ) {
file_put_contents ( ABSPATH . 'manifest.json', $newManifestJson );
} else {
// display an error
}

Cakephp Files and Folder class with regex to search for file

I am creating some sort of shell for removing backup files. I use to create backup of original file using keyword 'bkp'. It could be anywhre in file name either like this ["abc.bkp.ctp", "abc-bkp.ctp", abc_bkp.ctp", "bkp_abc.ctp"]. I mean any way. I wish to remove all files using shell. I am using Cakephp's Files N Folder Class "http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html". How would I write regex to search for these files.
Whats my shell logic is.
public function removeBkp() {
$path = BASE_PATH . DS . APP_DIR . DS;
$count = 0;
$this->out("", 2);
$this->out("-------------------------------------", 1);
$this->out("Path : " . $path, 1);
$this->out("FILES DETAILS", 1);
$this->out("-------------------------------------", 2);
$dir = new Folder($path);
// Need to seach bkp files here
$defaultFiles = $dir->findRecursive("(bkp)");
$results = $defaultFiles;
if ($results == null || empty($results)) {
$this->out("No file to delete.", 3);
} else {
foreach ($results as $file) {
// unlink($file);
$this->out("File removed - " . $file, 1);
$count++;
}
$this->out("Total files: " . count($results), 1);
}
}
You can match all filenames with this regex:
([\w._-]*bkp[\S]*?\.ctp)
Assuming only ._- are used to split the files up, you may need to add more to that character class.
This regex also assumes that the file always ends with ctp.
Demo: https://regex101.com/r/tB9nM9/1
EDIT: If you wish to match any extension, you can generalise the extension with \w{3}. Where 3 is the length, you can add variance here if needed, but more specific is usually better.
([\w._-]*bkp[\S]*\.\w{3})
DEMO: https://regex101.com/r/tB9nM9/2

Does anybody know how to add meta box template select to custom post type in Wordpress?

does anybody know how I can achieve the following:
I have a custom post type called 'projects' I have 5 different page
layouts (each with a different number of images at different sizes
that are arranged differently). I think that if I can ID the images I
can position them using CSS. If each layout has it's own template page
with containers for the required images and each also has CSS to
position the images.
I am wondering if it's possible to add a
template select on right hand side of post editor view, like you have
available for pages this way it's possible to assign a template (from
1-5) for each post.
I am adding custom meta boxes for the image upload fields
and the other data in the main post editor, but ideally this should
change for the other pages to only display the required upload
fields.
Any ideas anybody? I did consider setting up a custom post type for each layout (the 5 templates) allowing you to post a new project under the layout type you require, then on the page query the loop with all 5 custom-post-types (layouts). I worry this might be messy though, because to find projects to edit later you will need to know which template page (custom-post-type) they belong to but more importantly the url to projects wouldn't be www.sitename.co.uk/projects but instead be www.sitename.co.uk/custom-post-type1, www.sitename.co.uk/custom-post-type2 ??? Wouldn't it?
Any help really appreciated as always. Thanks
here is code I have identified so far, any ideas how to customise?
Should this go in functions.php?
// Check if the post has a special template
$template = get_post_meta($post->ID, '_wp_mf_page_template', true);
if (!$template || $template == 'default') {
return;
}
$template = TEMPLATEPATH.'/'.$template;
if ( $template = apply_filters( 'template_include', $template ) ) {
include($template);
die();
}
return;
Second code:
// Check if the post_type has page attributes
// if is the case is necessary need save the page_template
if ($_POST['post_type'] != 'page' && isset($_POST['page_template'])) {
add_post_meta($post_id, '_wp_mf_page_template', $_POST['page_template'], true) or update_post_meta($post_id, '_wp_mf_page_template', $_POST['page_template']);
}
Third code:
//MF Meta box for select template
function mf_metabox_template () {
global $post;
if ( 0 != count( get_page_templates() ) ) {
$template = get_post_meta($post->ID, '_wp_mf_page_template', TRUE);
$template = ($template != '') ? $template : false;
?>
<label class="screen-reader-text" for="page_template"><?php _e('Page Template') ?></label><select name="page_template" id="page_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php page_template_dropdown($template); ?>
</select>
<?php
}
}
You can create meta box using this code. Please paste this code in your function.php.
/*********************custom meta box********************************/
add_action( 'add_meta_boxes', 'add_events_metaboxes' );
function add_events_metaboxes() {
add_meta_box('wpt_school_location', 'Business Listing Data:','wpt_school_location', 'businesses', 'side', 'default');
}
//add_meta_box( $id, $title, $callback, $page, $context, $priority, $callback_args );
// Add the Events Meta Boxes
// The Event Location Metabox
function wpt_school_location() {
global $post;
// Noncename needed to verify where the data originated
echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
// Get the location data if its already been entered
$email = get_post_meta($post->ID, '_location', true);
$tel = get_post_meta($post->ID, '_location1', true);
$web = get_post_meta($post->ID, '_location2', true);
$city = get_post_meta($post->ID, '_location3', true);
// Echo out the field
echo '<div class="heading">Address</div>';
echo '<input type="text" name="_location" value="' . $email . '" class="widefat" />';
echo '<div class="heading">Telephone</div>';
echo '<input type="text" name="_location1" value="' . $tel . '" class="widefat" />';
echo '<div class="heading">E-mail</div>';
echo '<input type="text" name="_location2" value="' . $web . '" class="widefat" />';
echo '<div class="heading">Web</div>';
echo '<input type="text" name="_location3" value="' . $city . '" class="widefat" />';
}
// Save the Metabox Data
function wpt_save_events_meta($post_id, $post) {
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if ( !wp_verify_nonce( $_POST['eventmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
// Is the user allowed to edit the post or page?
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
// OK, we're authenticated: we need to find and save the data
// We'll put it into an array to make it easier to loop though.
$events_meta['_location'] = $_POST['_location'];
$events_meta['_location1'] = $_POST['_location1'];
$events_meta['_location2'] = $_POST['_location2'];
$events_meta['_location3'] = $_POST['_location3'];
// Add values of $events_meta as custom fields
foreach ($events_meta as $key => $value) { // Cycle through the $events_meta array!
if( $post->post_type == 'revision' ) return; // Don't store custom data twice
$value = implode(',', (array)$value); // If $value is an array, make it a CSV (unlikely)
if(get_post_meta($post->ID, $key, FALSE)) { // If the custom field already has a value
update_post_meta($post->ID, $key, $value);
} else { // If the custom field doesn't have a value
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key); // Delete if blank
}
}
add_action('save_post', 'wpt_save_events_meta', 1, 2); // save the custom fields
// Add the Events Meta Boxes