JSON data
{
"product_list": [
{
"title": "Title Name",
}
,
{
"title": "another title"
}
]
}
Mustache template
{{#product_list}}
{{title}}
{{/product_list}}
Expecting
> Title name
> Another title
But it is not showing anything. Using {{.}} showing the string representation of the product object. I want to access property of object on each iteration.
UPDATE
public function render()
{
$this->mustache=new \Mustache_Engine(array(
'template_class_prefix' => '__MyTemplates_',
'cache' => dirname(__FILE__) . '/tmp/cache/mustache',
'cache_file_mode' => 0666, // Please, configure your umask instead of doing this :)
'cache_lambda_templates' => true,
'loader' => new \Mustache_Loader_FilesystemLoader($templateDir),
'partials_loader' => new \Mustache_Loader_FilesystemLoader($templateDir . DIRECTORY_SEPARATOR .'partials'),
'helpers' => array('i18n' => function($text) {
// do something translatey here...
}),
'escape' => function($value) {
return htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
},
'charset' => 'ISO-8859-1',
'logger' => new \Mustache_Logger_StreamLogger('php://stderr'),
'strict_callables' => true,
'pragmas' => [\Mustache_Engine::PRAGMA_FILTERS],
));
return $this->mustache->render($this->template,$data);
}
UPDATE var_dump() of $data
array (size=2)
'product_list' =>
array (size=2)
0 =>
object(Product)[7]
private 'title' => string 'Title Name' (length=10)
1 =>
object(Product)[7]
private 'title' => string 'another title' (length=13)
Related
I've created a custom module in Drupal 8 that grab some data from an API, and puts them in the Drupal DB creating a new table.
I want to add this data as the contents of a specific content type.
How can I do that?
here is my code :
<?php
/**
* Implements hook_cron().
*/
function ods_cron() {
$message = 'Cron run: ' . date('Y-m-d H:i:s');
$ods = \Drupal::service('ods.ods');
$conf = \Drupal::service('ods.ods_configuration_request');
if ($conf->isDevelopment()) {
// Development
$response_bond = beforeSendRequest($conf->devUrlExternalBond(), 'GET');
$response_mf = beforeSendRequest($conf->devUrlExternalMutualFund(), 'GET');
} else {
// Production
$parameters_bond = [
'headers' => $conf->headers(),
'authorization' => $conf->basicAuthorization(),
'data_post' => $conf->bodyBond(),
];
$parameters_mf = [
'headers' => $conf->headers(),
'authorization' => $conf->basicAuthorization(),
'data_post' => $conf->bodyMutualFund(),
];
$response_bond = beforeSendRequest($conf->urlExternalBond(), 'POST', $parameters_bond);
$response_mf = beforeSendRequest($conf->urlExternalMutualFund(), 'POST', $parameters_mf);
}
$raw_result_bond = json_decode($response_bond);
$raw_result_mf = json_decode($response_mf);
// Development
if ($conf->isDevelopment()) {
$raw_result_bond = json_decode($raw_result_bond[0]->field_bonds);
$raw_result_mf = json_decode($raw_result_mf[0]->field_api);
}
$BondsProductList = $raw_result_bond->BondsProductInqRs->BondsProductList;
$MFProductInqList = $raw_result_mf->MFProductInqRs->MFProductInqList;
// Bond data store to internal
if ($BondsProductList !== null) {
$bond_datas = [];
foreach ($BondsProductList as $row => $content) {
$bond_datas[] = [
'AskPrice' => number_format($content->AskPrice, 1, '.', ','),
'BidPrice' => number_format($content->BidPrice, 1, '.', ','),
'BuySettle' => number_format($content->BuySettle, 1, '.', ','),
'CouponFreqCode' => $content->CouponFreqCode,
'CouponFreqID' => number_format($content->CouponFreqID),
'CouponRate' => number_format($content->CouponRate, 2, '.', ','),
'IDCurrency' => $content->IDCurrency,
'LastCoupon' => $content->LastCoupon,
'MaturityDate' => $content->MaturityDate,
'MinimumBuyUnit' => number_format($content->MinimumBuyUnit),
'MultipleOfUnit' => number_format($content->MultipleOfUnit),
'NextCoupon' => $content->NextCoupon,
'Penerbit' => $content->Penerbit,
'ProductCode' => $content->ProductCode,
'ProductName' => $content->ProductName,
'ProductAlias' => $content->ProductAlias,
'RiskProfile' => $content->RiskProfile,
'SellSettle' => $content->SellSettle
];
}
$insert_data = $ods->setData(
'bond',
[
'AskPrice', 'BidPrice', 'BuySettle', 'CouponFreqCode', 'CouponFreqID', 'CouponRate', 'IDCurrency',
'LastCoupon', 'MaturityDate', 'MinimumBuyUnit', 'MultipleOfUnit', 'NextCoupon', 'Penerbit',
'ProductCode', 'ProductName', 'ProductAlias', 'RiskProfile', 'SellSettle'
],
$bond_datas
);
if ($insert_data) {
// make response as JSON File and store the file
$ods->makeJsonFile($bond_datas, 'feeds/bonds', 'bond.json');
}
}
// Mutual Fund data store to internal
if ($MFProductInqList !== null) {
$mf_datas = [];
foreach ($MFProductInqList as $row => $content) {
$mf_datas[] = [
'ProductCode' => $content->ProductCode,
'ProductName' => $content->ProductName,
'ProductCategory' => $content->ProductCategory,
'ProductType' => $content->ProductType,
'Currency' => $content->Currency,
'Performance1' => $content->field_1_tahun_mf,
'Performance2' => $content->Performance2,
'Performance3' => $content->Performance3,
'Performance4' => $content->Performance4,
'Performance5' => $content->Performance5,
'UrlProspektus' => $content->UrlProspektus,
'UrlFactSheet' => $content->UrlFactSheet,
'UrlProductFeatureDocument' => $content->UrlProductFeatureDocument,
'RiskProfile' => $content->RiskProfile,
'FundHouseName' => $content->FundHouseName,
'NAVDate' => $content->NAVDate,
'NAVValue' => $content->NAVValue
];
}
$insert_data_mf = $ods->setData(
'mutual_fund',
[
'ProductCode', 'ProductName', 'ProductCategory', 'ProductType', 'Currency', 'Performance1', 'Performance2', 'Performance3',
'Performance4', 'Performance5', 'UrlProspektus', 'UrlFactSheet', 'UrlProductFeatureDocument', 'RiskProfile', 'FundHouseName',
'NAVDate', 'NAVValue'
],
$mf_datas
);
if ($insert_data_mf) {
// make response as JSON File and store the file
$ods->makeJsonFile($mf_datas, 'feeds/mf', 'mutual_fund.json');
}
}
// console log
\Drupal::logger('ods')->notice($message);
}
So can I store the data to pristine drupal 8 table?
First, you need to create the content type in the Drupal 8 backend going to Structure > Content type.
Second you can add a node programmatically like this
use Drupal\node\Entity\Node;
$node = Node::create(array(
'type' => 'your_content_type',
'title' => 'your title',
'langcode' => 'en',
'uid' => '1',
'status' => 1,
'body'=> 'your body',
));
$node->save();
I try to have logic in my transaction, but it just keeps adding the data to the database and I don't know what's going wrong...
The code I currently have:
public function addQuote($customer_id, Request $request)
{
//try catch, since there can be errors in it
DB::transaction(function() use ($customer_id, $request) {
try {
// Make a project for a quote, but not a main project, to not interfere with other existing projects
$quote_project = QuoteProject::create([
'projectnumber' => $request->project_number,
'name' => $request->project_name,
'address' => $request->project_address,
'zipcode' => $request->project_zipcode,
'city' => $request->project_city,
'country' => $request->project_country ?? 'BE',
'customer_id' => $customer_id,
]);
// Make a quote
$quote = Quote::create([
'status_id' => 1, // assign pending status
'reference' => $request->reference,
'number' => rand(),
'department_id' => $request->department,
'project_id' => $quote_project->id, // Created project id
'location_id' => ($request->location === 0) ? null : $request->location, // location -> can be 0 as value, if so, leave empty
'customer_id' => $customer_id,
'contact_id' => $request->contact_id,
'layout_id' => $request->layout_id,
'seller_id' => $request->seller_id,
'date_from' => Carbon::createFromFormat('d/m/Y', $request->date_from)->format('Y-m-d'),
'date_till' => Carbon::createFromFormat('d/m/Y', $request->date_till)->format('Y-m-d'),
'document_number' => $request->document_number,
'customer_number' => $request->customer_number,
'vat_type_id' => $request->vat_type_id,
'vat_tariff_id' => $request->vat_tariff_id,
]);
$quote->conditions()->attach($request->payment_conditions);
if (isset($request->head_group)) {
// set a global sync data variable
$sync_data = [];
// Loop over all the head groups
foreach ($request->head_group as $key => $head_group) {
// create or update head group
$created_head_group = ArticleGroup::updateOrCreate([
'quote_id' => $quote->id,
'name' => $head_group ?? ''
], [
'comment' => $request->head_group_comment[$key] ?? '',
'head_group' => 1,
'parent_group' => null,
'bold' => filter_var($request->bold_head[$key], FILTER_VALIDATE_BOOLEAN) ?? false,
'italic' => filter_var($request->italic_head[$key], FILTER_VALIDATE_BOOLEAN) ?? false,
'underline' => filter_var($request->underline_head[$key], FILTER_VALIDATE_BOOLEAN) ?? false,
'color' => str_replace('#', '', $request->color_head[$key]) ?? null
]);
// Loop over the sub groups in a main group
foreach ($request->sub_group[$key] as $s_key => $sub_group) {
// Create or update a subgroup
$created_sub_group = ArticleGroup::updateOrCreate([
'quote_id' => $quote->id,
'name' => $sub_group ?? ''
], [
'comment' => $request->sub_group_comment[$key][$s_key] ?? '',
'head_group' => 0,
'parent_group' => $created_head_group->id,
'bold' => filter_var($request->bold_sub[$key][$s_key], FILTER_VALIDATE_BOOLEAN) ?? false,
'italic' => filter_var($request->italic_sub[$key][$s_key], FILTER_VALIDATE_BOOLEAN) ?? false,
'underline' => filter_var($request->underline_sub[$key][$s_key], FILTER_VALIDATE_BOOLEAN) ?? false,
'color' => str_replace('#', '', $request->color_sub[$key][$s_key]) ?? null
]);
// Loop over the articles in the subgroup
foreach ($request->articles[$key][$s_key] as $a_key => $article_id) {
if (isset($request->articles[$key][$s_key])) {
$id = explode('-', $article_id);
$sync_data[$id[0]] = [
'name' => $request->custom_article_name[$key][$s_key][$a_key],
'quantity' => $request->quantity[$key][$s_key][$a_key],
'thickness' => $request->thickness[$key][$s_key][$a_key],
'price' => $request->article_price[$key][$s_key][$a_key],
'description' => $request->description[$key][$s_key][$a_key],
'group_id' => $created_sub_group->id
];
}
}
}
}
$quote->articles()->sync($sync_data); // sync the articles
}
// return data for ajax call, since the wizard works via an ajax call submit
return url('customers/' . $customer_id . '/quotations/');
} catch (\Exception $ex) {
return response()->json(['error' => $ex->getMessage()], 500);
}
}
);
}
If someone could explain me what I'm doing wrong here, that would be a really great help!
This is how it works. If inside DB::transaction exception is thrown then transaction is rolled back automatically. However in your implementation exception is not thrown because you catch it inside transaction and just try to return error response (what by the way won't work because you miss return in DB::transaction(function() use ($customer_id, $request) { line).
The easiest way to solve is to catch exception not inside DB::transaction but outside of it - then it will behave as you expected, transaction will be rolled back.
Alternative solution in some cases it not using DB::transaction but instead using manual:
DB::beginTransaction();
DB::rollBack();
DB::commit();
as described in documentation.
I have an object function to send news to an API:
class Manager
{
public function __construct(GuzzleHttp\Client $client)
{
$this->client = $client;
}
public function uploadNews($title, $text, $timestamp = null)
{
// DEFAULT FOR PUBLISH TIMESTAMP IS SET IF VALUE IS NULL
$timestamp = $timestamp ?? time();
$requestBody = [
'header' => [
'Accept' => 'application/json',
],
'timeout' => 300,
'body' => [
'title' => $title,
'text' => $text,
'publish_date' => $timestamp,
]
];
return $this->client->request('POST', 'http://api/endpoint', $requestBody);
}
}
How do I write a PHPUnit unit test to test the final $request passed to the client's request() function is of the expected format, when the $timestamp is not set (the API expects a timestamp)? I've written a unit test. But is not ideal, since there could be a difference in the tow timestamps.
class ManagerTest extends \PHPUnit\Framework\TestCase
{
public function testCanUploadNewsWithoutTimestamp()
{
$expectedRequestBody = [
'header' => [
'Accept' => 'application/json',
],
'timeout' => 300,
'body' => [
'title' => 'News title',
'text' => 'News article sample text.',
'publish_date' => time(),
]
];
$guzzleMock = $this->createMock(GuzzleHttp\Client::class);
$guzzleMock->expects($this->once())
->method('request')
->with(
'POST',
'http://api/endpoint',
$expectedRequestBody
);
(new Manager($guzzleMock))->uploadNews(
'News title',
'News article sample text.'
);
}
}
This is my current test result:
Parameter 2 for invocation GuzzleHttp\Client::request('POST', 'http://api/endpoint', Array (...)) does not match expected value.
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
## ##
'body' => Array (
'title' => 'News title'
'text' => 'News article sample text.'
- 'publish_date' => 1574550178
+ 'publish_date' => 1574550179
)
)
Please note that the only thing I need to make sure is that the timestamp is passed with request. The value of the timestamp doesn't matter.
PS: I'm really new to Test Driven Development, so the answer might be obvious and I might still not know it.
I'm using laravel and this :
https://github.com/comodojo/metaweblog/
Here is the code in controller:
public function testNewPost() {
$mwlog = new MetaWeblog("http://example.org/services/metablog.ashx","user","pass");
$struct = array(
'title' => "Test Post",
'description' => "Test Post description",
'post_type' => "post",
'categories' => array('uncategorized'),
'mt_keywords' => array('test','post'),
'mt_allow_comments' => "open",
'mt_allow_pings' => "open"
);
$post = $mwlog->newPost($struct);
}
But it returns :
Input string was not in a correct format.
What's wrong?!
I'm trying to migrate my current html site into drupal. I have over 80,000 pages I have to migrate so I thought instead of sitting infront of a computer for 50 years I would create a module. I was able to create a script that extracts the html from each directory and now I got to a road block where I need to create a node. I'm trying to create a new node using node_save(), but when node_save is executed, I get a PDOException error with everything I try. I'm passing in $node, which is an array which is then casted into an object.
PDOException: in field_sql_storage_field_storage_write() (line 424 of /srv/www/htdocs/modules/field/modules/field_sql_storage/field_sql_storage.module).
This is how we are currently creating the node, but it produces an error:
$node= array(
'uid' => $user->uid,
'name' => $user->name,
'type' => 'page',
'language' => LANGUAGE_NONE,
'title' => $html['title'],
'status' => 1,
'promote' => 0,
'sticky' => 0,
'created' => (int)REQUEST_TIME,
'revision' => 0,
'comment' => '1',
'menu' => array(
'enabled' => 0,
'mlid' => 0,
'module' => 'menu',
'hidden' => 0,
'has_children' => 0,
'customized' => 0,
'options' => array(),
'expanded' => 0,
'parent_depth_limit' => 8,
'link_title' => '',
'description' => '',
'parent' => 'main-menu:0',
'weight' => '0',
'plid' => '0',
'menu_name' => 'main-menu',
),
'path' => array(
'alias' => '',
'pid' => null,
'source' => null,
'language' => LANGUAGE_NONE,
'pathauto' => 1,
),
'nid' => null,
'vid' => null,
'changed' => '',
'additional_settings__active_tab' => 'edit-menu',
'log' => '',
'date' => '',
'submit' => 'Save',
'preview' => 'Preview',
'private' => 0,
'op' => 'Save',
'body' => array(LANGUAGE_NONE => array(
array(
'value' => $html['html'],
'summary' => $link,
'format' => 'full_html',
),
)),
'validated' => true,
);
node_save((object)$node);
// Small hack to link revisions to our test user.
db_update('node_revision')
->fields(array('uid' => $node->uid))
->condition('vid', $node->vid)
->execute();
Usually I create a bulkimport.php script in the document root to do this kind of thing.
Here is the code I use for Drupal 7:
<?php
define('DRUPAL_ROOT', getcwd());
include_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
function _create_node($title="", $body="", $language="und") {
$node = (object)array();
$node->uid = '1';
$node->name = 'admin';
$node->type = 'page';
$node->status = 1;
$node->promote = 0;
$node->sticky = 0;
$node->revision = 1;
$node->language = $language;
$node->title = $title;
$node->body[$language][0] = array(
'value' => $body,
'format' => 'full_html',
);
$node->teaser = '';
$node->log = 'Auto Imported Node';
node_submit($node);
node_save($node);
return $node;
} ### function _create_node
$sith = array(
'Darth Vader' => 'Master: Darth Sidious',
'Darth Sidious' => 'Master: Darth Plagous',
'Darth Maul' => 'Master: Darth Sidious',
'Darth Tyranous' => 'Master: Darth Sidious',
);
foreach($sith as $title=>$body) {
print "Creating Node. Title:[".$title."] \tBody:[".$body."] ";
$node = _create_node($title, $body);
print "\t... Created Node ID: [".$node->nid."]\n";
#print_r($node);
} ### foreach
I was getting exactly the same error as in your original post -
PDOException: in field_sql_storage_field_storage_write()
- etc.
I was already using the stdClass code style shown in the comments above.
The problem turned out to be the pound signs and accented chars in the string I was assigning to the Body field; the strings were coming from a Windows text file.
Converting the string to the Drupal target encoding (UTF-8) worked for me:
$cleaned_string = mb_convert_encoding($html['html'], "UTF-8", "Windows-1252");
$node->body[LANGUAGE_NONE][0]['value'] = $cleaned_string;
$node->body[LANGUAGE_NONE][0]['format'] = 'plain_text';
node_save($node);
Hope this helps someone.
are you using some CMS engine, or it is custom-written website?
in first case, look here http://drupal.org/documentation/migrate
I strongly recommend you to look at the given modules, they should help. Also, as an option, to migrate DB.
You don't need a lot of those blank fields. Also, you can cast the node as an object rather than an array converted to an object.
Your code should be able to be accomplished with this much shorter snippet:
$node = new stdClass();
$node->title = $html['title'];
$node->type = 'page';
$node->body['und'][0]['value'] = $html['html'];
node_save($node);
Also, there's a number of methods that have been developed to mass-import nodes into Drupal - I am a fan of the Feeds module (http://drupal.org/project/feeds). This may require writing a method of exporting your existing content to an intermediary format (CSV or XML), but it works reliably and you can re-import nodes to update content when required.