On a cs-cart project, I am looking for a clean way to automate the migration of the current theme in a fully automatic manner.
Migrating the theme files is easy since each theme is located in a dedicated directory.
Nevertheless, some pages are created using the layouts WYSIWIG editor from the backend. This editor as a nice feature that allows to generate an XML file that describes all the layouts and can be imported back into another environment. This requires manual operation (logging into the backend, clicking the button...) and I would like to fully automate this.
So far, the only solution I was able to find is to migrate the data directly from the database, by generating a dump of the layout related-tables and importing it into the target environment. This solution seems to work but is a bit risky in my opinion.
Does cs-cart provide a command-line interface to export and import the current layouts?
I wrote a small script for this task:
<?php
use Tygh\BlockManager\Layout;
use Tygh\BlockManager\Exim;
if ($mode == "do") {
$location_ids = array();
$default_layout_data = Layout::instance()->getDefault();
$layout_id = $default_layout_data['layout_id'];
$content = Exim::instance()->export($layout_id, $location_ids);
header("Content-Type: text/xml");
header("Content-Length: " . strlen($content));
header('Content-Disposition: attachment; filename=layouts.xml');
header('Expires: 0');
print $content;
exit();
}
if you put this code to a controller file (for example into your /app/addons/my_changes/controllers/backend/layout_export.php) and call this via url (in my case: /youradmin.php?dispatch=layout_export.do), it will download the default theme's main layout structure.
Please note, that I'm working with version 4.3.3. However I think this code will work any type of CS-Cart from version 4.x
Full solution (with my_changes add-on)
/app/addons/my_changes/schemas/permissions/trusted_controllers.post.php
<?php
$schema['layout_exim']['allow']['export'] = true;
$schema['layout_exim']['allow']['import'] = true;
return $schema;
/app/addons/my_changes/controllers/backend/layout_exim.php
<?php
use Tygh\BlockManager\Layout;
use Tygh\BlockManager\Exim;
if ($mode == "export") {
$location_ids = array();
$default_layout_data = Layout::instance()->getDefault();
$layout_id = $default_layout_data['layout_id'];
$content = Exim::instance()->export($layout_id, $location_ids);
header("Content-Type: text/xml");
header("Content-Length: " . strlen($content));
header('Content-Disposition: attachment; filename=layouts.xml');
header('Expires: 0');
print $content;
exit();
} elseif ($mode == "import") {
$result = Exim::instance()->importFromFile($_REQUEST['filepath']);
if ($result) {
print "true";
} else {
print "false";
}
exit();
}
After it, please clear your cache. If you do everything right, you will be able to call these 2 controllers without authentication (however I suggest you to set passwords in the get parameters, because right now, this is very unsafe!)
To call the controllers via URL:
http://path-to-your-admin.com/admin.php?dispatch=layout_exim.import&filepath=path/to/file
http://path-to-your-admin.com/admin.php?dispatch=layout_exim.export
Related
I installed dompdf using composer
composer require dompdf/dompdf
in my controller i have this
use Dompdf\Dompdf;
....
function actionPdf() {
$dompdf = new DOMPDF();
$dompdf->loadHtml('<h1>hello world</h1>');
$dompdf->setPaper('A4', 'landscape');
$dompdf->render();
}
but all i get is a blank PDF. When i check app.log i see this
2021-09-02 20:20:41 [127.0.0.1][262][-][error][yii\web\HeadersAlreadySentException] yii\web\HeadersAlreadySentException: Headers already sent in on line 0. in C:\xampp\htdocs\yii2\vendor\yiisoft\yii2\web\Response.php:373
Stack trace:
#0 C:\xampp\htdocs\yii2\vendor\yiisoft\yii2\web\Response.php(346): yii\web\Response->sendHeaders()
#1 C:\xampp\htdocs\yii2\vendor\yiisoft\yii2\base\Application.php(398): yii\web\Response->send()
#2 C:\xampp\htdocs\yii2\frontend\web\index.php(64): yii\base\Application->run()
#3 {main}
Any Idea how to fix this? Thanks
Not sure the exact proper Yii way, but in my case this works:
Note the exit(); at the end.
// instantiate and use the dompdf class
$dompdf_options = new \Dompdf\Options();
$dompdf_options->setDpi(150);
$dompdf = new Dompdf($dompdf_options);
$dompdf->loadHtml($html);
// (Optional) Setup the paper size and orientation
$dompdf->setPaper('A4');
// Render the HTML as PDF
$dompdf->render();
$attachment=false;
$options=[
"Attachment" => $attachment
];
// Output the generated PDF to Browser
$dompdf->stream('Informe de vehículo', $options);
exit();
I guess the problem is caused by how Yii renders the data. But by calling exit() you prevent any of that to happen.
I have two nearly identical php functions both are functioning but for some reason the header will only run on the first one. I have no idea why this could be happening. I've seen some similarly titled post but none have solved or are the same as the problem I have so please don't remove this question. I've tried removing the closing php tag no help I've tried just about everything you could imagine but no cigar. the code is definitely running as echo's work at the end of the code so does exit(); but for some reason header just doesn't work. Any help would be greatly appreciated I will try anything. Also the reason I need this to work is so that when the page is refreshed it doesn't resubmit the form. I know this isn't much to go on so feel free to ask me questions.
function setComments($conn){
if (isset($_POST['commentsubmit'])) {
$uid = $_POST['uid'];
$date = $_POST['date'];
$message = mysqli_real_escape_string($conn, $_POST['message']);
$sql = "INSERT INTO comments (uid, date, message) values('$uid','$date', '$message')";
$result = mysqli_query($conn,$sql);
header("Location: videos.php");
}
}
duplicate code with alterations.
function setComments2($conn){
if (isset($_POST['commentsubmit2'])) {
$uid = $_POST['uid'];
$date = $_POST['date'];
$message = mysqli_real_escape_string($conn, $_POST['message']);
$sql = "INSERT INTO comments2 (uid, date, message) values('$uid','$date','$message')";
$result = mysqli_query($conn,$sql);
header("Location: home.html");
}
}
The header function calls were located AFTER other code.
PHP.net says this:
"Remember that header() must be called BEFORE any actual output is
sent, either by normal HTML tags, blank lines in a file, or from PHP.
It is a very common error to read code with include, or require,
functions, or another file access function, and have spaces or empty
lines that are output before header() is called. The same problem
exists when using a single PHP/HTML file."
I've created an API module in prestaShop and I am generating an XML output to a certain CMS page. Thing is that I can't disable the layout.
I just need to render the XML output from the module (and no html).
Any ideas please? (I am not using the webservice classes)
At least.. Is it possible to do this from a module?
Thanks,
Dan
Override the method "display" of your controller and output whatever you want.
If you do not want to display layout, do not call parent::display().
I have a problem like you. And I knew how to disable it.
You just need add two lines below to your module:
$this->display_header = false;
$this->display_footer = false;
Example:
public function initContent(){
parent::initContent();
$this->display_header = false;
$this->display_footer = false;
$this->setTemplate('display.tpl');
}
I've trying to get properly work kcaptcha class from kcaptcha.ru in my own component. 'Cause class not build for Joomla natively I break my brain on the wall.
And at the beginning...
I've a url to image generated by this class like: http://.../index.php&task=captcha&format=raw
In main controller I've put method
function captcha() {
include(JPATH_COMPONENT.DS.'libraries'.DS.'captcha'.DS.'kcaptcha'.DS.'kcaptcha.php');
$session = &JSession::getInstance('default', array());
$captcha = new KCAPTCHA();
if ($session) {
$session->set('captcha_keystring', $captcha->getKeyString());
}
}
And I've see in browser
When I request an image from the class all working good but in my component I cannot set session variables.
Any ideas how to fix this problem?
And problem solved successfully.
For &format=raw in controller Joomla set default mime-type to text/html.
For healing this issue developer must reset mime/type via setting
$document = &JFactory::getDocument();
$document->setMimeEncoding('image/png');
mime/encoding off course depends on you needs.
I have a view that displays several nodes. I want to place node form below each displayed node. Both node_add and drupal_get_form directly in template.php works fine, but I get forms with same form ID of NODETYPE_node_form and validation and submitting does not work as expected.
If you had to put several node forms on one page, what would be your general approach?
Progress so far...
in template.php while preprocessing node
$author_profile and $content is set before.
$unique = $vars['node']->nid;
$node = new StdClass();
$node->uid = $vars['user']->uid;
$node->name = $vars['user']->name;
$node->type = 'review';
$node->language = '';
$node->title = t('Review of ') . $vars['node']->realname . t(' by ') . $vars['user']->realname . t(' on ') . $content->title;
$node->field_review_to_A[0]['nid'] = $nodeA->nid;
$node->field_review_to_B[0]['nid'] = $vars['node']->nid;
$node->field_review_to_profile[0]['nid'] = $author_profile->nid;
if(!function_exists("node_object_prepare")) {
include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
}
//$vars['A_review_form'] = drupal_get_form('review_node_form', $node);
$vars['A_review_form'] = mymodule_view($node, $unique);
in mymodule module
function mymodule_view($node, $unique) {
if(!function_exists("node_object_prepare")) {
include_once(drupal_get_path('module', 'node') . '/node.pages.inc');
}
$output = drupal_get_form('review_node_form_' . $unique, $node);
return $output;
}
function mymodule_forms($form_id, $args) {
$forms = array();
if (strpos($form_id, "review_node_form_") === 0) {
$forms[$form_id] = array('callback' => 'node_form');
}
return $forms;
}
function mymodule_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node']) && $form_id != $form['type']['#value'] .'_node_form' && $form['type']['#value'] == 'review') {
$type = content_types($form['#node']->type);
if (!empty($type['fields'])) {
module_load_include('inc', 'content', 'includes/content.node_form');
$form = array_merge($form, content_form($form, $form_state));
}
$form['#pre_render'][] = 'content_alter_extra_weights';
$form['#content_extra_fields'] = $type['extra'];
//$form['#id'] = $form_id;
//$form['#validate'][0] = $form_id . '_validate';
$form['title']['#type'] = 'value';
$form['field_review_to_A']['#type'] = 'value';
$form['field_review_to_B']['#type'] = 'value';
$form['field_review_to_profile']['#type'] = 'value';
}
}
Questions
My take on summarizing unclear questions...
Is this good general approach for displaying multiple node forms on same page?
Is it OK to copy/paste code from content modules content_form_alter function in function mymodule_form_alter? Will it not brake things if content module is updated?
Should i set $form['#id']? Without it all forms has same HTML form ID of node_form, with it ID is unique, like review_node_form_254. Thing is that there is no difference of how form is submitted. Setting $form['#validate'][0] does not seem to influence things too. Maybe I should set $form[button]['#submit'][0] to something else? Now its node_form_submit.
Why validation does not work even with unique form id and form validate function? If i submit last form without required field all previous forms gets particular fields red. should I make my own validation function? what level - form or field? Any tips on where to start?
You need to implement hook_forms() to map different ids to the same builder function.
The NODETYPE_node_form ids you mention are already an example of this mechanism, as they are all mapped to the same builder function (node_form()) within the node modules node_forms() implementation.
You can find links to more examples in the 'Parameters' explanation off the drupal_get_form() function.
This was exceptionally useful to me.
Documentation on all the drupal APIs is so lacking - I was tearing my hair out. The crucial bit for me, that I don't think is covered anywhere else on the net:
CCK adds its fields to your form through hook_form_alter() . But it does this based on the form_id. So if the form ID is different (cause you want multiple ones on the same page), you need to replicate a bit of the CCK code to add the fields to your form regardless.
That is what this does brilliantly.
I really did not dig to the bottom of it, but it seems to me that you pretty much did all the relevant digging by yourself.
From what I understand by inspecting the code only, you are right in thinking that content_form_alter() is the show-stopper.
Maybe this is a naïve suggestion, but what about writing your own implementation of hook_form_alter() starting from the content_form_alter() code but changing the conditions that make the alteration to occur? I am thinking to something along these lines:
function modulename_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node']) &&
stripos($form_id, $form['type']['#value'] .'_node_form')) {
...
}
}
I did not actually test the code above, but I hope it is self-explenatory: you actually trigger the changes for a give customised type of content if MYCCKTYPE_node_form is a substring of the actual form_id (es: MYCCKTYPE_node_form_234).
Hope this helps at least a bit... Good luck! :)
EDIT: TWO MORE THINGS
It just occurred to me that since your custom implementation of hook_form_alter() will live aside the CCK one, you would like to add a check to avoid the form to be modified twice something like:
&& $form_id != $form['type']['#value'] .'_node_form'
The other way you might try to implement this by not using CCK but implementing you custom type programmatically (this might even be an advantage if you plan to use your module on various different sites).