Yii2: renderPartial error => error on line 1 at column 1: Document is empty - layout

I am using Krajee mdpf tool(http://demos.krajee.com/mpdf) on Yii 2. I tried to generate a view and I succeed with the render() function. The problem is that it displays a layout. So I decided to use renderPartial() function to only display the htlm of the view but I get this error:
This page contains the following errors:
error on line 1 at column 1: Document is empty
error on line 1 at column 1: Encoding error
Below is a rendering of the page up to the first error.
Here is my actionPdfTest function:
public function actionPdfTest()
{
// get your HTML raw content without any layouts or scripts
$content = Yii::$app->controller->renderPartial('_example');
// setup kartik\mpdf\Pdf component
$pdf = new Pdf([
// set to use core fonts only
'mode' => Pdf::MODE_CORE,
// A4 paper format
'format' => Pdf::FORMAT_A4,
// portrait orientation
'orientation' => Pdf::ORIENT_PORTRAIT,
// stream to browser inline
'destination' => Pdf::DEST_BROWSER,
// your html content input
'content' => $content,
// format content from your own css file if needed or use the
// enhanced bootstrap css built by Krajee for mPDF formatting
'cssFile' => '#vendor/kartik-v/yii2-mpdf/src/assets/kv-mpdf-bootstrap.min.css',
// any css to be embedded if required
'cssInline' => '.kv-heading-1{font-size:18px}',
// set mPDF properties on the fly
'options' => ['title' => 'Krajee Report Title'],
// call mPDF methods on the fly
'methods' => [
'SetHeader'=>['Krajee Report Header'],
'SetFooter'=>['Krajee Report Footer'],
]
]);
// return the pdf output as per the destination setting
return $pdf->render();
}
Code of _example view:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* #var $this yii\web\View */
/* #var $form yii\widgets\ActiveForm */
/* #var $model app\models\LoginForm */
$this->title = 'Hello World';
?>
<h1><?= Html::encode($this->title) ?></h1>
Please Can you help me?

Thank you every body,
I found the solution. It was to add :
Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
before the:
$content = Yii::$app->controller->renderPartial('_example');
Here is the final code:
public function actionPdfTest()
{
Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
// get your HTML raw content without any layouts or scripts
$content = Yii::$app->controller->renderPartial('_example');
// setup kartik\mpdf\Pdf component
$pdf = new Pdf([
// set to use core fonts only
'mode' => Pdf::MODE_CORE,
// A4 paper format
'format' => Pdf::FORMAT_A4,
// portrait orientation
'orientation' => Pdf::ORIENT_PORTRAIT,
// stream to browser inline
'destination' => Pdf::DEST_BROWSER,
// your html content input
'content' => $content,
// format content from your own css file if needed or use the
// enhanced bootstrap css built by Krajee for mPDF formatting
'cssFile' => '#vendor/kartik-v/yii2-mpdf/src/assets/kv-mpdf-bootstrap.min.css',
// any css to be embedded if required
'cssInline' => '.kv-heading-1{font-size:18px}',
// set mPDF properties on the fly
'options' => ['title' => 'Krajee Report Title'],
// call mPDF methods on the fly
/*
'methods' => [
'SetHeader'=>['Krajee Report Header'],
'SetFooter'=>['Krajee Report Footer'],
]
*/
]);
// return the pdf output as per the destination setting
return $pdf->render();
}

this error Message mostly appears, if there is no correct handling of http-header, document-format and/or sending output to the browser.
I don't know, what return $pdf->render(); exactly is doing. But I guess your problem is a mix of sending wrong header, sending header multiple times and/or sending output that doesn't matches the header.
So you should think about:
What output-type you expect for your script? Check, if you set the http-Header that matched your output type.
Check if $pdf->render(); outputs something more than the return value.
If $pdf->render() returns an pdf, you should send this as file to the browser, like that ("pseudo-code"). Using sendFile, sendContentAsFile or sendStreamAsFile depends on the output of $pdf->render() ( https://www.yiiframework.com/doc/guide/2.0/en/runtime-responses#sending-files )
return Yii::$app->response->sendContentAsFile(
$pdf->render(),
"download.pdf",
['inline' => true,
'mimeType' => 'application/pdf']

Related

Accessing Nested Attributes in a WordPress Gutenberg block via PHP

I have a working WordPress Gutenberg Block project which uses nested blocks. I'm trying to rewrite the javascript save function in PHP to create a dynamic block.
I've modified the PHP file to include the following:
function render_html($attributes) {
var_dump($attributes);
ob_start(); ?>
<h1>Attributes</h1>
<h3>The number of columns is <?php echo esc_html($attributes['myColumns']) ?>!</h3>
<?php return ob_get_clean();
}
function cards_init() {
register_block_type_from_metadata( __DIR__, array(
'render_callback' => 'render_html'
) );
}
add_action( 'init', 'cards_init' );
This displays the top level attributes correctly (just one value):
C:\Users\Steve\Local Sites\netmonics6\app\public\wp-content\plugins\cards\cards.php:32:
array (size=1)
'myColumns' => int 3
Attributes
The number of columns is 3!
I'm just wondering how I access the attributes for the nested blocks?
I've used Innerblocks in the main edit.js as follows to enable a nested block:
<InnerBlocks
allowedBlocks={['some-name/card']}
orientation="horizontal"
template={[
['some-name/card'],
['some-name/card'],
['some-name/card'],
]}
/>
Does anyone please have any ideas?
Steve
InnerBlocks can be accessed via $block in the render_callback function. The syntax for the render callback is function($attributes, $content, $block) although commonly, only $attributes is used - unless you want to access something <InnerBlocks>, eg:
PHP
/*
* Render callback function
* #return string HTML markup
*/
function render_html($attributes, $content, $block)
{
$output = '';
// Loop through each inner block
foreach ($block->inner_blocks as $inner_block) {
// Eg. If your ['some-name/card'] block had an attribute
// called `someAttribute` (boolean), it could be accessed via:
if ($inner_block->someAttribute == true) {
// Do something different with this block
$output .= sprintf('<div class="is-some-attribute">%s</div>', $inner_block->render());
} else {
// Otherwise, render block as usual..
$output .= $inner_block->render();
}
}
/*
* Tip: Always return the content to render
* echo() should not be used in render_callback() and ob_start/ob_get_clean not needed.
* Returning valid content avoids dreaded "Invalid JSON" error in Editor.
*/
return $output;
}
When using InnerBlocks, the save() function in JavaScript is required so that the block editor saves the InnerBlock content (even if you are using a PHP render_callback), eg:
save.js
export default function save() {
const blockProps = useBlockProps.save();
return (
<div {...blockProps}>
<InnerBlocks.Content />
</div>
)
}
Depending on what you need from the InnerBlocks, block context might also be useful too..

drupal views: how to invoke swftools media player for emfields?

I am using swftools to display filefields (Drupal 6).
Now I would like to use swftools to display the custom-url emfields (embedded media fields). For example, if my emaudio field contains the url http://example.com/myaudio.mp3. I would like to use the swftools audio player to play this mp3 file.
I know how to invoke the swftools player, if I am displaying a node that contains an emfield. I use hook_preprocess_content_field() to replace $items[0]['view'] with swf($items[0]['value']):
function mytheme_preprocess_content_field(&$vars) {
foreach ($vars['items']as $index=>$arr){
// Note:
// Emfield's custom_url video provider is called "zzz_custom_url".
// Emfield's custom_url audio provider is called "custom_url"
if ($arr['provider']=='zzz_custom_url' || $arr['provider']=='custom_url'){
$vars['items'][$index]['view'] = swf($arr['value']);
}
}
}
But I do not know how to invoke the swf player if I am displaying a view that contains an emfield. That is, I have not been able to figure out how to pull off a similar trick when I am displaying a view rather than a node. Any suggestions?
I have a solution.
I created a views template to theme my emaudio field,
views-view-field--field-my-emaudio-embed.tpl.php
Here is the content of the template:
$data = $row->{$field->field_alias};
print swf($data);
Another solution:
Create the custom formatter "SWF Emaudio", as described below. Then select this formatter to display your custom-url emaudio field, from within the cck or views UI.
function mymodule_field_formatter_info() {
$formatters = array();
$formatters['swf_emaudio'] = array(
'label' => t('SWF Emaudio'),
'field types' => array('emaudio'),
);
}
function mymodule_theme() {
$themes['mymodule_formatter_swf_emaudio'] = array(
'arguments' => array('element' => NULL, 'options' => array()),
'function' => 'theme_o4_mediatools_formatter_swf_emaudio',
);
}
return ($themes);
}
function theme_mymodule_formatter_swf_emaudio($element, $options = array()) {
$embed_value = $element['#item']['value'] ;
$output = swf($embed_value, $options);
return ($output);
}

drupal 6 : node.tpl.php $links variable, where to configure the content?

I need to define the order of the $links output
now I have 2 modules displaying its contents on that:
comments and addthis
where can I define the order of the and modify it's settings for nodes...
even customize a little bit the display?
Edit: links weights can be changed using http://drupal.org/project/linkweights
I am not sure there is any kind of UI for reordering/customizing the node links.
However you can accomplish this in a couple of ways:
Create a custom module that implements hook_link_alter() and perform the customizations.
/**
* hook_link_alter() implementation
* for more details see
* http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_link/6
* http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_link_alter/6
*/
function mymodule_link_alter(&$links, $node) {
foreach ($links as $link => $values) {
// do something with $link
}
return $links;
}
You can go even further and create an administration page that will get all the links, output them in a sortable table (a la /admin/build/block) and save the order in a variable. Ah, your module needs to have the highest weight in order to catch all the other links.
--OR--
Modify your theme's template.php and add the mytheme_preprocess_node() function or edit it or phptemplate_preprocess_node() if it exists
function phptemplate_preprocess_node(&$vars) {
$links= $vars['node']->links;
// uncomment the next line to see the current links
//var_dump($links);
// add a new link
$link_all = array(
'title' => 'See all nodes',
'href' => PATH,
//'attributes' => array('class' => 'link_class', 'id' => 'link_id', 'title' => 'link title'),
);
$links['link_all'] = $link_all;
//Modify an existing link. in this case the above added one
$links['link_all']['title'] = t('This is my custom text');
$vars['links'] = theme_links($links);
}
To reorder see http://drupal.org/node/44435#comment-861385

Drupal 6 File Handling

I am handling file upload field in a form using Drupal 6 form APIs. The file field is marked as required.
I am doing all the right steps in order to save and rename files in proper locations.
upload form
$form = array();
....
$form['image'] = array(
'#type' => 'file',
'#title' => t('Upload photo'),
'#size' => 30,
'#required' => TRUE,
);
$form['#attributes'] = array('enctype' => "multipart/form-data");
...
form validate handler
$image_field = 'image';
if (isset($_FILES['files']) && is_uploaded_file($_FILES['files']['tmp_name'][$image_field])) {
$file = file_save_upload($image_field);
if (!$file) {
form_set_error($image_field, t('Error uploading file'));
return;
}
$files_dir = file_directory_path();
$contest_dir = 'contest';
if(!file_exists($files_dir . '/' . $contest_dir) || !is_dir($files_dir . '/' . $contest_dir))
mkdir($files_dir . '/' . $contest_dir);
//HOW TO PASS $file OBJECT TO SUBMIT HANDLER
$form_state['values'][$image_field] = $file;
file_move($form_state['values'][$image_field], $files_dir."/" . $contest_dir . "/contest-". $values['email']. "-" . $file->filename);
}
else {
form_set_error($image_field, 'Error uploading file.');
return;
}
On submiting form
Form always reports an error Upload photo field is required. although files are getting uploaded. How to deal with this issue?
How to pass file information to submit handler?
your handler is wrong. You never should touch $_FILES or $_POST variables in drupal, instead you should only use the drupal tools. Said that, the implementation you should is like that:
function my_form_handler(&$form,&$form_state){/** VALIDATION FILE * */
$extensions = 'jpeg jpg gif tiff';
$size_limit = file_upload_max_size();
$validators = array(
'my_file_validate_extensions' => array($extensions),
'my_file_validate_size' => array($size_limit),
);
$dest = file_directory_path();
if ($file = file_save_upload('image', $validators, $dest)) {
//at this point your file is uploaded, moved in the files folder and saved in the DB table files
}
}
I think you'll want to use the filefield module and append it to a form, as described in:
Drupal Imagfield/Filefield in custom form
The question has a link to the solution:
http://sysadminsjourney.com/content/2010/01/26/display-cck-filefield-or-imagefield-upload-widget-your-own-custom-form
From the Drupal 6 Form API docs:
"Note: the #required property is not supported (setting it to true will always cause a validation error). Instead, you may want to use your own validation function to do checks on the $_FILES array with #required set to false. You will also have to add your own required asterisk if you would like one."
Old post, but I'm looking for something similar and figured I add that.

Drupal 6: Working with Hidden Fields

I am working on an issue i'm having with hooking a field, setting the default value, and making it hidden. The problem is that it is taking the default value, but only submitting the first character of the value to the database.
//Here is how I'm doing it
$form['field_sr_account'] = array( '#type' => 'hidden', '#value' => '45');
I suppose there is something wrong with the way that I have structured my array, but I can't seem to get it. I found a post, http://drupal.org/node/59660 , where someone found a solution to only the first character being submitted
//Here is the format of the solution to the post - but it's not hidden
$form['field_sr_account'][0]['#default_value']['value'] = '45';
How can I add the hidden attribute to this?
Have you tried using #default_value insted of #value?
Also if you're trying to pass some data to the submit that will not be changed in the form you should use http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html#value .
The answer was actually to set the value and the hidden attribute separately, then set the value again in the submit handler using the following format.
I'm not sure if it's all necessary, I suppose I probably don't need to assign it in the form alter, but it works, so I'm going to leave it alone...
$form['#field_sr_account'] = $club;
$form['field_sr_account'] = array( '#type' => 'hidden','#value' => $club);
}
}
/*in submit handler, restore the value in the proper format*/
$form_state['values']['field_sr_account'] = array('0' => array('value' => $form['#field_sr_account']));
An interesting solution from http://drupal.org/node/257431#comment-2057358
CCK Hidden Fields
/**
* Implementation of hook_form_alter().
*/
function YourModuleName_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node'])) {
### Make a CCK field becoming a hidden type field.
// ### Use this check to match node edit form for a particular content type.
if ($form_id === 'YourContentTypeName_node_form') {
$form['#after_build'] = array('_test_set_cck_field_to_hidden');
}
}
}
function _test_set_cck_field_to_hidden($form, &$form_state) {
$form['field_NameToBeHidden'][0]['value']['#type'] = 'hidden';
$form['field_NameToBeHidden'][0]['#value']['value'] = 'testValue';
return $form;
}

Resources