how is possible to set the margins on the new 7 version?
I want to remove the margins of the pages, setting on 0. In the version 6 I set them into new mPDF( but now I don't know how is possible
on the 6 I used :
$pdf = new \mPDF('utf-8', 'A4'.($orientation == 'L' ? '-L' : ''), '', '', $margin_left, $margin_right, $margin_top, $margin_bottom, 0, 0);
now?
thanks
mPDF 7 constructor has a signature of
\Mpdf\Mpdf::__construct([array $config = []])
You need to pass an array of values with appropriate keys, which for margins are margin_left, margin_right, margin_top, margin_bottom, margin_header and margin_footer.
The whole code would then be
$mpdf = \Mpdf\Mpdf::__construct([
'margin_left' => $margin_left,
'margin_right' => $margin_right,
'margin_top' => $margin_top,
'margin_bottom' => $margin_bottom,
'margin_header' => 0,
'margin_footer' => 0,
])
All this and other constructor $config keys is written on the mPDF constructor documentation page.
Related
For a project I am currently trying to write a mini pilot assistance system for an imaginary aircraft. The task is to learn Ada Spark, not avionics. I have modelled the plane components I wish to use, done some tests in the main file to check the components work as expected, and all is fine, and now I am to add pre and post conditions to functions to make sure my plane is super safe. One such safety measure is to make sure the engine cannot be switched on whilst the plane is in tow, or vice versa, switch to tow whilst the engine is on.
I have modelled an engine as a highly complex record, with one attribute, type OnOff, which takes one of the values On, or Off. Note I plan on expanding upon the attributes, so it isn't going to remain a one attribute record.
Here is the engines specification file
package engines with SPARK_Mode
is
type OnOff is (On, Off);
type Engine is record
isOn: OnOff;
end record;
procedure switchOn (x : in out Engine);
procedure switchOff (x : in out Engine);
end engines;
My plane is put together like so:
type Plane is record
engine1: Engine;
engine2: Engine;
gearOfLanding: LandingGear;
doorPax1, doorPax2, doorServ1, doorServ2,
doorCockpit: Door;
panelOfReadings: ReadingsPanel;
panelOfAlerts: AlertsPanel;
planOfFlight: FlightPlan;
speedLimits: SpeedLimit;
altitudeLimits: AltitudeLimit;
attitudeLimits: AttitudeLimit;
litresPerMile: Integer;
fuelTank1: FuelTank;
end record;
The procedure switchOnEngine within the planes file takes an engine as an input and calls switchOn from the engines file. Here is the specification and below, the body:
procedure switchOnEngine (x : in out Engine; y : in Plane) with
Pre => y.panelOfReadings.mode /= Tow,
Post => x = (isOn => On) and y.panelOfReadings.mode /= Tow;
procedure switchOnEngine (x : in out Engine; y : in Plane)
is
begin
switchOn(x);
end switchOnEngine;
The plane is passed in as a variable so I can check various attributes for my pre and post conditions, but I am getting warning messages I am unsure how to resolve.
precondition might fail
cannot prove y.panelOfReadings.mode /= Tow e.g when .......mode =>Tow
The following line is also giving an error from the main file where I control my plane
switchOnEngine(AirForceOne.engine1, AirForceOne);
formal parameters x and y are aliased, and this is being marked as a 'high' priority warning.
here is the initialisation of the plane in the main file
AirForceOne : Plane := (
engine1 => (isOn => Off),
engine2 => (isOn => Off),
litresPerMile => 5,
gearOfLanding => (isExtended => Extended),
doorPax1 => (isClosed => Closed, isLocked => Unlocked),
doorPax2 => (isClosed => Closed, isLocked => Unlocked),
doorServ1 => (isClosed => Closed, isLocked => Unlocked),
doorServ2 => (isClosed => Closed, isLocked => Unlocked),
doorCockpit => (isClosed => Closed, isLocked => Unlocked),
fuelTank1 => (capacity=>26000, currentFuel=>26000),
planOfFlight => (distFromDest => 1500),
panelOfReadings =>
(mode => Tow,
currentSpeed => 0,
altitud => 0,
attitud =>
(currentPitch=>0,
currentRoll =>0)
),
panelOfAlerts =>
(approachingStallSpeed => Off,
unRestrictedSpeed => Off,
withinLandingSpdRange => Off,
withinOptCruiseAlt => Off,
withinOptCruiseSpeed => Off,
takeoffSpeedReached => Off,
fuelStatus => Off,
maxPitchAngleExceeded => Off,
maxRollAngleExceeded => Off),
speedLimits =>
(minLanding => 180,
maxLanding => 200,
minStall => 110,
minTakeoff => 130,
maxRestricted => 300,
maxGroundMode => 10),
altitudeLimits =>
(minFlight => 500,
maxFlight => 41000,
optCruiseAlt => 36000,
maxRestrictedSpeed => 10000,
maxInitiateFlareMode => 100),
attitudeLimits =>
(maxRoll => 30,
maxPitch => 30,
minRoll => -30,
minPitch => -30)
);
Any help would be great. I thought it would be enough to suggest in the pre condition that the plane cannot be in tow, but it seems to not be enough.
The purpose of Switchonengine is to change the state of the plane. Writing it to change the state of an engine is going to complicate things.
Max_Engines : constant := 100; -- The Lillium jet has 36, so I hope this is enough
type Engine_Num is range 1 .. Max_Engines;
type Engine_Info is ...
type Engine_Map is array (Engine_Num range <>) of Engine_Info with
Dynamic_Predicate => Engine_Map'First = 1;
type Plane_Info (Num_Engines : Engine_Num) is record
Engine : Engine_Map (1 .. Num_Engines);
...
procedure Turn_On (Engine : in Engine_Num; Plane : in out Plane_Info) with
Pre => Engine in 1 .. Plane.Num_Engines and then
(not Running (Plane.Engine (Engine) ) and not Under_Tow (Plane),
Post => Running (Plane.Engine (Engine) );
Air_Force_One : Plane_Info (Num_Engines => 4);
I need to translate variable-length sentences in Symfony 3.4.
Sample sentence: "Included: 4 breakfasts, 1 brunch and 3 dinners."
For the exemple let's say the following constraints:
I have to express the number of breakfasts, brunches, lunches and dinners that a travel may have in a full itinerary
The list of "things" to enumerate is known and finite. There is singular and plural translation for each of the key-words.
Not all of them have to appear. If there are 0 units, the full block will be omitted.
The list is comma-separated.
Except the last block which is added with an "and" connector.
If there's only 1 block there's no comma and no "and" connector.
Each can be singular/plural.
There are multiple languages, for this example I'll use English and Spanish, but in the reality there is also catalan.
The keywords are the following in english-singular / english-plural / spanish-singular / spanish-plural:
breakfast / breakfasts / desayuno / desayunos
brunch / brunches / alumerzo-desayuno / almuerzo-desayunos
lunch / lunches / almuerzo / almuerzos
dinner / dinners / cena / cenas
So... I can imagine the following tests cases:
[
'language' => 'en-US',
'parameters' => [
'breakfast' => 4,
'dinner' => 1,
],
'expectedOutput' => 'Included: 4 breakfasts and 1 dinner.'
],
[
'language' => 'es-ES',
'parameters' => [
'breakfast' => 2,
'brunch' => 1,
'lunch' => 5,
'dinner' => 2,
],
'expectedOutput' => 'Incluido: 2 desayunos, 1 desayuno-almuerzo, 5 almuerzos y 2 cenas.'
],
[
'language' => 'en-US',
'parameters' => [
'breakfast' => 1,
],
'expectedOutput' => 'Included: 1 breakfast.'
],
[
'language' => 'es-ES',
'parameters' => [
'dinner' => 4,
'lunch' => 3,
],
'expectedOutput' => 'Incluido: 3 almuerzos y 4 cenas.'
],
Questions
Is this supported by the native translation engine in Symfony 3.4?
If not, is this supported by the native translation engines of Symfony 4 or 5?
Otherwise, is there any known pattern or strategy that fits this case?
What the translation engine can do to some extent is use a number to switch between different cases (for singular/plural). Have a look at transChoice for symfony 3.4 (til 4.1.x apparently). Since symfony 4.2, the ICU message format (follow links too) may be used to handle pluralization.
However, (conditional) string building is not really a task for the translation engine at all (even though for simple cases transChoice or the ICU message format might work out fine). So you'll probably end up building the strings from bits and pieces.
Building the string in php
// fetch translations for the itemss
$items = [];
foreach($parameters as $key => $count) {
if($count <= 0) {
continue;
}
$items[] = $translator->transChoice($key, $count);
}
// handle 2+ items differently from 1 item
if(count($items) > 1) {
// get last item
$last = array_pop($items);
// comma-separate all other items, add last item with "and"
$itemstring = implode(', ', $items)
. $translator->trans('included_and')
. $last;
} else {
$itemstring = $items[0] ?? ''; // if no items or something like
// $translator->trans('included_none')
}
return $translator->trans('included', ['%items%' => $itemstring]);
and in the translation file (english):
'included' => 'Included: %items%.',
'included_and' => ' and ',
'breakfast' => '%count% breakfast|%count% breakfasts', // etc. for all other stuff
Please note, that transChoice should automatically set the %count% placeholder to the count provided as the second parameter to transChoice.
alternate approaches
You could easily split the translatable strings into breakfast_singular and breakfast_plural if you wanted to avoid the use of transChoice, you would have to replace
transChoice($key, $count)
with
trans($key.($count > 1 ? '_plural' : '_singular'), ['%count%' => $count])
You could also expand the included string into included_single and included_multiple where the latter is being translated as 'Included: %items% and %last%', with appropriate parameters and conditionals.
Ultimately though, string generation or more specifically language generation isn't really a job for a simple translation engine.
im building my request data as an array structure and want to use the symfony XmlEncoder to encode my Array to XML.
so i guess i got the fundamental part right, it looks like that for example:
$request_object = [
"acc-id" => $all_credentials,
"req-id" => $request_guid,
"tran-type" => "spec-url"
];
the syntax im looking for encodes in the following format, with attribute and value:
<amount currency="EUR">1.99</amount>
i have the possiblity to use the # sign on an array key, but how to also fit in the value?
$request_object = [
"acc-id" => $all_credentials,
"req-id" => $request_guid,
"tran-type" => "spec-url"
"am" => ["#attr"=>"attrval"]
];
this should be
<am attr="attrval"/>
but how to write it that i can also set the value? like:
<am attr="attrval">VALUE</am>
help is much appreciated
Use '#' as the index for the scalar value.
I found it by looking through the tests for the encoder.
#src:https://github.com/symfony/serializer/blob/master/Tests/Encoder/XmlEncoderTest.php
#line: 196
public function testEncodeScalarRootAttributes()
{
$array = [
'#' => 'Paul',
'#eye-color' => 'brown',
];
$expected = '<?xml version="1.0"?>'."\n".
'<response eye-color="brown">Paul</response>'."\n";
$this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
}
...
#line: 234
public function testEncodeScalarWithAttribute()
{
$array = [
'person' => ['#eye-color' => 'brown', '#' => 'Peter'],
];
$expected = '<?xml version="1.0"?>'."\n".
'<response><person eye-color="brown">Peter</person></response>'."\n";
$this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
}
I have read in a lot of sources that I should use the geofield_compute_values() function when trying to programmatically save coordinates in Drupal.
However it does not work for me, that function is undefined in the Drupal 8.5.2 that I am using.
I've installed geofield using composer and I can use it as usual in the admin area and there are no problems with saving there.
Here are some examples I've tried with, the first example gives me undefined function geofield_compute_values() :
$geofield_data = geofield_compute_values([
'lat' => $lat,
'lon' => $lon,
], GEOFIELD_INPUT_LAT_LON);
$cbisProduct->set('field_koordinater', $geofield_data);
I have also tried this out with no successful result and no errors :
$geofield = [
'geom' => "POINT (" . $lon . " " . $lat . ")",
'geo_type' => 'point',
'lat' => $lat,
'lon' => $lon,
'left' => $lon,
'top' => $lat,
'right' => $lon,
'bottom' => $lat,
];
$cbisProduct->set('field_koordinater', $geofield);
Seems like you're trying to use the geofield_compute_values() function which was available in 7.x version, but not in 8.x
You should look into the wkt_generator service. i.e.
<?php $wktGenerator = \Drupal::service('geofield.wkt_generator'); ?>
I haven't tried this, but something like this should work:
<?php
$point = [
'lat' => $request->get('lat'),
'lon' => $request->get('lon'),
];
$value = \Drupal::service('geofield.wkt_generator')->WktBuildPoint($point);
$node->field_koordinater->setValue($value);
Also, WktGeneratorTest.php and GeofieldItemTest.php files could be a good start to see how to use the service in your implementation.
This function is not available in Drupal 8. You have to rely on the basic GeofieldItem class that extends FieldItemBase. Also, as mentioned by oman, you can use WktGenerator to easily build points, polygons, etc.
Here a working example. Let's say your have an entity $cbisProduct with a multivalued geofield field_koordinater, and you want to set the first item with arbitrary lat/lon coordinates :
// Get geofield item
$geofield = $cbisProduct->get('field_koordinater')->get(0);
// Generate a point [lat, lon]
$coord = ['45.909621', '6.127147'];
$point = \Drupal::service('geofield.wkt_generator')->WktBuildPoint($coord);
// Calling this function will compute values AND assign geodata to the field instance
$geofield->setValue($point);
// You can read the computed geodata from the field
$geodata = $geofield->getValue();
//dpm($geodata);
// Explicitly set field data (needed if $geofield is not a reference)
$cbisProduct->set('field_koordinater', [$geodata]);
// Save entity
$cbisProduct->save();
Under the hood, GeofieldItem::setValue calls another method responsible to directly assign the computed values to the field instance :
# \Drupal\geofield\Plugin\Field\FieldType\GeofieldItem
protected function populateComputedValues() {
/* #var \Geometry $geom */
$geom = \Drupal::service('geofield.geophp')->load($this->value);
if (!empty($geom)) {
/* #var \Point $centroid */
$centroid = $geom->getCentroid();
$bounding = $geom->getBBox();
$this->geo_type = $geom->geometryType();
$this->lon = $centroid->getX();
$this->lat = $centroid->getY();
$this->left = $bounding['minx'];
$this->top = $bounding['maxy'];
$this->right = $bounding['maxx'];
$this->bottom = $bounding['miny'];
$this->geohash = substr($geom->out('geohash'), 0, GEOFIELD_GEOHASH_LENGTH);
$this->latlon = $centroid->getY() . ',' . $centroid->getX();
}
}
Note : You don't necessarily need WktGenerator for building points, as long as you know the geofield type and how geophp should handle it. For example, the following 2 statements are equivalent :
$point = \Drupal::service('geofield.wkt_generator')->WktBuildPoint($coord);
// is equivalent to
$point = GEOFIELD_TYPE_POINT . '(' . implode(' ', $coord) . ')');
But it is safer to rely on the WktGenerator especially with more complex data types.
I have this line of code:
var inventory = dbInventory.Data
.SqlQuery( sql )
.OrderBy( m => m.isSold )
.ThenBy( m => m.lotNumber )
.ToList();
I this code for 4 pages on my website, the order is correct for the 3 out of the 4, for the 4th one, they dont want to go in order at all. For the one that is not working, all the isSold is false and they all have a lotNumber but its not returning the lotNumbers in order.
Please help.
This fixed my problem.
var inventory = dbInventory.Data.SqlQuery(sql).OrderBy(m => m.isSold).ThenBy(m => int.Parse(m.lotNumber)).ToList();