How to check if some number is in_array in PhalconPHP volt? - arrays

I am looking for a in_array function equivalency in volt.
Is there another way to do this?
{% for modelObj in modelList %}
{% if modelObj.getId() in modelIdCheckedList %}
{{ check_field('id[]', 'value':modelObj.id, 'checked': true) }}
{% else %}
{{ check_field('id[]', 'value':modelObj.id, 'checked': null) }}
{% endif %}
{% endfor %}
I need to do something like this
{{ check_field('id[]', 'value':modelObj.id, 'checked': in_array(modelObj.getId(), modelIdCheckedList )) }}
Could you help me?

There are two ways you can achieve this.
Using a Function
Register the in_array as a function that Volt will understand. In your Volt registration you need to add the function to the compiler as follows:
$volt = new Phalcon\Mvc\View\Engine\Volt($view, $diContainer);
$volt->setOptions( .... );
$volt->getCompiler()->addFunction(
'in_array',
function ($parameters) {
return 'in_array(' . $parameters . ')';
}
);
Using an Extension
You can also register a PHP function extension, which will allow all PHP functions to work in Volt.
Create your extension class
class PhpFunctionExtension
{
/**
* This method is called on any attempt to compile a function call
*/
public function compileFunction($name, $arguments)
{
if (function_exists($name)) {
return $name . "(". $arguments . ")";
}
}
}
Register it in the Volt compiler
$volt = new Phalcon\Mvc\View\Engine\Volt($view, $diContainer);
$volt->setOptions( .... );
$volt->getCompiler()->addExtension(new PhpFunctionExtension());
https://docs.phalconphp.com/en/latest/reference/volt.html#extending-volt
https://docs.phalconphp.com/en/latest/reference/volt.html#extensions

Use the in operator:
{{ modelObj.getId() in modelIdCheckedList }}
So you may do something like:
{{ check_field('id[]', 'value': modelObj.id, 'checked': modelObj.getId() in modelIdCheckedList }}
Source: Volt - Other Operators

Related

StreamField : Add Map block

I'm working on a leaflet wagtail block integration.
https://github.com/frague59/wagtail-leaflet
I've difficulties with the widget rendering when I add the new block into the stream : nothing displays. The widget, from django-leaflet / django-geojson, involves the setting of geojson parameters 'window wide', which is not reflected in template instanciation.
In my leaflet/widget.html:
<script type="text/javascript">
{% block vars %}var {{ module }} = {};
{{ module }}.fieldid = '{{ id_css }}';
{{ module }}.modifiable = {{ modifiable|yesno:"true,false" }};
{{ module }}.geom_type = '{{ geom_type }}';
{{ module }}.srid = {{ map_srid }};
{% endblock vars %}
function {{ id_map_callback }}(map, options) {
window.LEAFLET_DATA['{{ module }}'].store_class = {{ field_store_class }};
(new {{ geometry_field_class}}(window.LEAFLET_DATA['{{ module }}'])).addTo(map);
{% block callback %}{% endblock callback %}
};
{% if target_map %}
window.addEventListener('map:init', function (e) {
var target_map = e.detail.map;
target_map.on('map:loadfield', function (me) {
if (me.fieldid == 'id_{{ target_map }}') {
setTimeout(function () {
{{ id_map_callback }}(target_map, e.detail.options);
}, 0);
}
});
}, false);
{% endif %}
</script>
From text/template element:
<script type="text/javascript">
var geodjango___prefix___value = {};
geodjango___prefix___value.fieldid = '__prefix__-value';
geodjango___prefix___value.modifiable = true;
geodjango___prefix___value.geom_type = 'Geometry';
geodjango___prefix___value.srid = 4326;
function __prefix___value_map_callback(map, options) {
geodjango___prefix___value.store_class = L.FieldStore;
(new L.GeometryField(geodjango___prefix___value)).addTo(map);
};
</script>
The Streamfield block API does not mention clearly this use case.
Do you have a working block example with this kind of block ?
Thanks !
Requirements:
django-leaflet
django-geosjon
jsonfield
The block definition: uses the leaflet widget from django-leaflet / django-geosjon
class GeoJSONBlock(FieldBlock):
geom_type = 'POINT'
def __init__(self, required=True, help_text=None, max_length=None, min_length=None, **kwargs):
if self.geom_type is None:
raise NotImplemented('You are attempting to use ``GeoJSONBlock`` directly, which *WILL* not work !')
self.field = GeoJSONFormField(required=required,
help_text=help_text,
max_length=max_length,
min_length=min_length,
geom_type=self.geom_type)
super(GeoJSONBlock, self).__init__(**kwargs)
def render_form(self, value, prefix='', errors=None):
"""
Renders ``edit`` form
:param value: current value
:param prefix: prefix of the form item
:param errors: Validations errors
:returns: HTML Fragment
"""
logger.debug('MapBlock::render_form() value = %s', value)
rendered = super(GeoJSONBlock, self).render_form(value=value, prefix=prefix, errors=errors)
return rendered
def render(self, value, context=None):
"""
Renders the widget in the web site
:param value: current value
:param context: Additional render context
:returns: HTML Fragment
"""
logger.debug('MapBlock::render() value = %s', value)
rendered = super(GeoJSONBlock, self).render(value=value, context=context)
return rendered
#property
def media(self):
return forms.Media(
js=['wagtailleaflet/leaflet_init.js', ]
)
def js_initializer(self):
"""
JS function to launch on start'up
:returns: JS function name, from ``wagtailleaflet/leaflet_init.js``
"""
output = 'drawMap'
logger.debug('MapBlock::js_initializer() output = %s', output)
return output
def html_declarations(self):
output = render_to_string('wagtailleaflet/leaflet_forms.html')
return output
Usage:
from wagtail.wagtailadmin.edit_handlers import StreamFieldPanel
from wagtail.wagtailcore.fields import StreamField
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore import blocks
from wagtailleaflet.blocks import GeoJSONPointBlock
class DemoPage(Page):
"""
Simple demo page
"""
body = StreamField([('text', blocks.RichTextBlock()),
('map', GeoJSONPointBlock()), ])
content_panels = Page.content_panels + [StreamFieldPanel('body')]
I've found that the problem comes from the leaflet implementation, which uses slugify (set the id to lower) to create the id, which breaks the __PREFIX__ replacement in sequence.js on block initialization.
It's a bit complicated to re-produce, that's why I did put the link to my repo with a demo wagtail project.

Symfony array of arrays

Maybe there is a simpler way of doing this. But I want to display entries (URLs) that were already found when trying to input in to a database table along with the current table. So in the controller I am trying to pass two arrays. One that is of the whole table and another of the entries it found matched the entries in the table. So the user can see they already existed.
$repository = $this->getDoctrine()->getRepository('ObjectBundle:object');
foreach ($mylinks as &$value) {
$linkexist = $repository->findOneByUrl($value);
if (!$linkexist) {
$obj = new Object();
$obj->setUrl($value);
$obj->setLastupdate(new \DateTime('now'));
$em = $this->getDoctrine()->getManager();
$em->persist($obj);
$em->flush();
} else {
$notfound = new Object();
$notfound->setUrl($value);
}
}
$em = $this->getDoctrine()->getManager();
$listurls = $em->getRepository('ObjectBundle:Object')->findAll();
return $this->render('object/index.html.twig', array(
'objects' => $listurls,
));
I would like to include the $notfound into a separate array or parse it without changing the Object entity. Any ideas?
You Object contains some sort of Id and it can be used here:
$existingIds = array();
$k=0;
Then collect the IDs:
} else {
$notfound = new Object();
$notfound->setUrl($value);
$nfound[$k]=$notfound;
$k++;
}
Pass the array:
return $this->render('object/index.html.twig', array(
'objects' => $listurls,
'existingIds' => $existingIds
));
Finally, in your Twig, you would have something like this:
{% if existingIds is defined %}
{% for existingId in existingIds %}
{{ existingId.url }}
{% endfor %}
{% endif %}
Hope this helps a bit...

Shopify String Replace Array not working

I am new to shopify but upon my research... this code should work.
{% assign dcor = "decor, decors, Decor, Decors" | split: ", "%}
{% assign dcors = "décor, décors, Décor, Décors" | split: ", "%}
{{ product.title | replace: 'dcor', 'dcors' }}
But no luck at all.
Nope. Won't work. You can't match/replace elements from arrays. You have to manually replace each variation
{% assign dcor = "decor, decors, Decor, Decors" | split: ", "%}
{% assign dcors = "décor, décors, Décor, Décors" | split: ", "%}
{% assign d = dcor.size | minus: 1 %}
{% for i in (0..d) %}
{% assign title = product.title | replace: dcor[i],dcors[i] %}
{% endfor %}
{{ title }}

Laravel 5 form another array from database result

I'm new to Laravel and I've been struggling too long with this now, tried to search SO and google for information but can't solve this.
I'm creating blog and need to make some kind of navigation/archive which displays year and months and how many blog posts there have been per year and invidual month. By clicking those years/months I would then display posts during that time period on different view.
I want them to be displayed in the view like this:
2015 (10)
January(3)
February(3)
March(3)
April(1)
2014 (2)
May(1)
June(1)
And so on.
I got database query like this:
$links = \DB::table('posts')
->select(\DB::raw('YEAR(created_at) year, MONTH(created_at) month, MONTHNAME(created_at) month_name, COUNT(*) id'))
->where('active',1)
->groupBy('year')
->groupBy('month')
->orderBy('year', 'desc')
->orderBy('month', 'desc')
->get();
Which gives me table like this:
array:3 [
0 => {#275
+"year": "2015"
+"month": "10"
+"month_name": "October"
+"id": "3"
}
1 => {#274
+"year": "2015"
+"month": "9"
+"month_name": "September"
+"id": "1"
}
2 => {#273
+"year": "2014"
+"month": "8"
+"month_name": "August"
+"id": "1"
}
]
How can I print it on my view like I described?
If I go through the array in views like this:
#foreach($links as $link)
<h3 class="text-uppercase">{{ $link->year }}</h3>
<p><small class="blog_date">{{ $link->month_name }} ({{ $link->id }}) </small>
#endforeach
I tried to use foreach-loop in my Controller to create another array from DB-results where structure would be in correct form and I could just use foreach to print it on the view, but couldn't get it work.
I know I'm near the solution, but I'm still learning. Please someone tell me which is the best way to do this.
Try this in your blade:
<?php $first_loop = 0; ?>
#foreach($links as $link)
#if($first_loop == 0)
<?php
$first_loop = 1;
$current_year = $link->year;
?>
<h3 class="text-uppercase">{{ $link->year }}</h3>
<p><small class="blog_date">{{ $link->month_name }} ({{ $link->id }}) </small></p>
#else
#if($current_year == $link->year)
<p><small class="blog_date">{{ $link->month_name }} ({{ $link->id }}) </small></p>
<?php
$current_year = $link->year;
?>
#else
<h3 class="text-uppercase">{{ $link->year }}</h3>
<p><small class="blog_date">{{ $link->month_name }} ({{ $link->id }}) </small></p>
<?php
$current_year = $link->year;
?>
#endif
#endif
#endforeach
You can do some preparation on your data before outputting it. For example:
$links = // .. your query;
$years = array_pluck($links, 'year');
$results = [];
foreach($years as $year)
{
$posts_count = 0;
$posts = array_where($links, function($key, $value) use ($year, $posts_count){
if($value['year'] == $year)
{
$posts_count += $value['id'];
return true;
}
return false;
});
$results[$year] = ['posts' => $posts, 'posts_count' => $posts_count];
}
You can do the above in some repository/service class, or even in the controller if you want (although not recommended)
And then in your view you can have something like:
#foreach($results as $year => $result)
{{ $year }} {{ data_get($result, 'posts_count') }}
<ul>
#foreach(data_get($result, 'posts') as $monthly_post)
<li>{{ data_get($monthly_post, 'month_name') }} {{ data_get($monthly_post, 'id') }}</li>
#endforeach
</ul>
#endforeach
This code is untested, so use it as inspiration for your approach, not a copy-paste solution.

GAE ReferenceProperty Error from option value

I'm trying to add a new Goal via POST using my select option populated by the Referenced Category. The dropdown populates correctly, but the key I'm getting from the value returned is causing a ReferenceProperty Error.
models.py:
class Categories(db.Model):
name = db.StringProperty(required=True)
amount = db.FloatProperty(required=True)
class Goals(db.Model):
name = db.StringProperty(required=True)
amount = db.FloatProperty(required=True)
category = db.ReferenceProperty(Categories)
add_goal.html:
select type="select" name="category" id="id_cat"
{% for c in cats %}
option value='{{c.name}}' {{ c.name }} /option
{% endfor %}
/select>
CORRECTED VERSION:
{% for c in cats %}
{{ c.name }}
{% endfor %}
views.py:
def post(self):
cat_key = db.Key.from_path('Categories', self.request.get('category'))
logging.info('cat_key= '+ str(cat_key))
g = Goals(name=self.request.get('name'),
category=cat_key,
amount=float(self.request.get('amount')))
g.put()
return webapp2.redirect('/view_goals')
CORRECTED VERSION:
def post(self):
cat_key = db.Key.from_path('Categories', int(self.request.get('category')))
g = Goals(name=self.request.get('name'),
category=cat_key,
amount=float(self.request.get('amount')))
g.put()

Resources