TCPDF: Get total number of pages / find out if it's the last page - tcpdf

I don't want page numbers on the first and last pages of my PDF so in my custom footer function I'm trying to compare the current page number to the total number of pages, which isn't working since $this->getAliasNbPages(); returns a string (something like "{ptp)"} which cannot be converted to an integer.
How do I get the total number of pages as an integer or otherwise find out if the current page is the last?

You can use
$this->getNumPages();

/**
* Reset pointer to the last document page.
* #param $resetmargins (boolean) if true reset left, right, top margins and Y position.
* #public
* #since 2.0.000 (2008-01-04)
* #see setPage(), getPage(), getNumPages()
*/
public function lastPage($resetmargins=false) {
$this->setPage($this->getNumPages(), $resetmargins);
}
/**
* Get current document page number.
* #return int page number
* #public
* #since 2.1.000 (2008-01-07)
* #see setPage(), lastpage(), getNumPages()
*/
public function getPage() {
return $this->page;
}
/**
* Get the total number of insered pages.
* #return int number of pages
* #public
* #since 2.1.000 (2008-01-07)
* #see setPage(), getPage(), lastpage()
*/
public function getNumPages() {
return $this->numpages;
}
originally from tcpdf.php you can find it all there

Related

Snowflake JSON to tabular

I was reading through the documentation of Snowflake and haven't found a solution yet so I come to you. I have a table in Snowflake which contains a variant column where I store JSON data. Do you know of a way to dynamically convert the results of a query on a variant column to a tabular format?
For example I have a query like
select json_data from database.schema.table limit 2
Which would return something like
JSON_DATA
{"EventName": "Test", "EventValue": 100}
{"EventName": "Test", "EventValue": 200}
Is there a way to return it as a table without having to reference the keys? I know I can do
select
json_data['EventName'] EventName,
json_data['EventValue'] EventValue
from
database.schema.table
But I am looking for something more dynamic like
select * from table(json_to_table(select json_data from database.schema.table)) limit 2
That could return
EventName
EventValue
Test
100
Test
200
I'm looking for any internal solutions (like stored procedures, udf, snowflake functions I might have missed...anything except external functions)
While there's no way to create dynamic column lists currently, as described in the comment you can run a stored procedure to build (and rebuild) a view. This will avoid having to manually type and maintain a long list of columns.
After creating the SP at the bottom, you can use it like this:
create or replace table MY_TABLE(JSON_DATA variant);
insert into MY_TABLE select parse_json('{"EventName": "Test", "EventValue": 100}');
insert into MY_TABLE select parse_json('{"EventName": "Test", "EventValue": 200}');
call create_view_over_json('MY_TABLE', 'JSON_DATA', 'MY_VIEW');
select * from MY_VIEW;
Here is the stored procedure to create the view. Note that if the table is very large it will take Snowflake's TYPEOF() function quite a while to determine a column type. If it's known to be consistent, you can point it to a sample table or one created with a limit 1000.
create or replace procedure create_view_over_json (TABLE_NAME varchar, COL_NAME varchar, VIEW_NAME varchar)
returns varchar
language javascript
as
$$
/****************************************************************************************************************
* *
* CREATE_VIEW_OVER_JSON - Craig Warman, Alan Eldridge and Greg Pavlik Snowflake Computing, 2019, 2020, 2021 *
* *
* This stored procedure creates a view on a table that contains JSON data in a column. *
* of type VARIANT. It can be used for easily generating views that enable access to *
* this data for BI tools without the need for manual view creation based on the underlying *
* JSON document structure. *
* *
* Parameters: *
* TABLE_NAME - Name of table that contains the semi-structured data. *
* COL_NAME - Name of VARIANT column in the aforementioned table. *
* VIEW_NAME - Name of view to be created by this stored procedure. *
* *
* Usage Example: *
* call create_view_over_json('db.schema.semistruct_data', 'variant_col', 'db.schema.semistruct_data_vw'); *
* *
* Important notes: *
* - This is the "basic" version of a more sophisticated procedure. Its primary purpose *
* is to illustrate the view generation concept. *
* - This version of the procedure does not support: *
* - Column case preservation (all view column names will be case-insensitive). *
* - JSON document attributes that are SQL reserved words (like TYPE or NUMBER). *
* - "Exploding" arrays into separate view columns - instead, arrays are simply *
* materialized as view columns of type ARRAY. *
* - Execution of this procedure may take an extended period of time for very *
* large datasets, or for datasets with a wide variety of document attributes *
* (since the view will have a large number of columns). *
* *
* Attribution: *
* I leveraged code developed by Alan Eldridge as the basis for this stored procedure. *
* *
****************************************************************************************************************/
var currentActivity;
try{
currentActivity = "building the query for column types";
var elementQuery = GetElementQuery(TABLE_NAME, COL_NAME);
currentActivity = "running the query to get column names";
var elementRS = GetResultSet(elementQuery);
currentActivity = "building the column list";
var colList = GetColumnList(elementRS);
currentActivity = "building the view's DDL";
var viewDDL = GetViewDDL(VIEW_NAME, colList, TABLE_NAME);
currentActivity = "creating the view";
return ExecuteSingleValueQuery("status", viewDDL);
}
catch(err){
return "ERROR: Encountered an error while " + currentActivity + ".\n" + err.message;
}
/****************************************************************************************************************
* *
* End of main function. Helper functions below. *
* *
****************************************************************************************************************/
function GetElementQuery(tableName, columnName){
// Build a query that returns a list of elements which will be used to build the column list for the CREATE VIEW statement
sql =
`
SELECT DISTINCT regexp_replace(regexp_replace(f.path,'\\\\[(.+)\\\\]'),'(\\\\w+)','\"\\\\1\"') AS path_name, -- This generates paths with levels enclosed by double quotes (ex: "path"."to"."element"). It also strips any bracket-enclosed array element references (like "[0]")
DECODE (substr(typeof(f.value),1,1),'A','ARRAY','B','BOOLEAN','I','FLOAT','D','FLOAT','STRING') AS attribute_type, -- This generates column datatypes of ARRAY, BOOLEAN, FLOAT, and STRING only
REGEXP_REPLACE(REGEXP_REPLACE(f.path, '\\\\[(.+)\\\\]'),'[^a-zA-Z0-9]','_') AS alias_name -- This generates column aliases based on the path
FROM
#~TABLE_NAME~#,
LATERAL FLATTEN(#~COL_NAME~#, RECURSIVE=>true) f
WHERE TYPEOF(f.value) != 'OBJECT'
AND NOT contains(f.path, '['); -- This prevents traversal down into arrays
`;
sql = sql.replace(/#~TABLE_NAME~#/g, tableName);
sql = sql.replace(/#~COL_NAME~#/g, columnName);
return sql;
}
function GetColumnList(elementRS){
/*
Add elements and datatypes to the column list
They will look something like this when added:
col_name:"name"."first"::STRING as name_first,
col_name:"name"."last"::STRING as name_last
*/
var col_list = "";
while (elementRS.next()) {
if (col_list != "") {
col_list += ", \n";
}
col_list += COL_NAME + ":" + elementRS.getColumnValue("PATH_NAME"); // Start with the element path name
col_list += "::" + elementRS.getColumnValue("ATTRIBUTE_TYPE"); // Add the datatype
col_list += " as " + elementRS.getColumnValue("ALIAS_NAME"); // And finally the element alias
}
return col_list;
}
function GetViewDDL(viewName, columnList, tableName){
sql =
`
create or replace view #~VIEW_NAME~# as
select
#~COLUMN_LIST~#
from #~TABLE_NAME~#;
`;
sql = sql.replace(/#~VIEW_NAME~#/g, viewName);
sql = sql.replace(/#~COLUMN_LIST~#/g, columnList);
sql = sql.replace(/#~TABLE_NAME~#/g, tableName);
return sql;
}
/****************************************************************************************************************
* *
* Library functions *
* *
****************************************************************************************************************/
function ExecuteSingleValueQuery(columnName, queryString) {
var out;
cmd1 = {sqlText: queryString};
stmt = snowflake.createStatement(cmd1);
var rs;
try{
rs = stmt.execute();
rs.next();
return rs.getColumnValue(columnName);
}
catch(err) {
throw err;
}
return out;
}
function GetResultSet(sql){
try{
cmd1 = {sqlText: sql};
stmt = snowflake.createStatement(cmd1);
var rs;
rs = stmt.execute();
return rs;
}
catch(err) {
throw err;
}
}
$$;

Transform Flux to Mono, execute method on Mono and transform back to Flux

I need to implement this function:
// TODO Capitalize the users username, firstName and lastName
// using #asyncCapitalizeUser method below
Flux<User> asyncCapitalizeMany(Flux<User> flux) {
}
Mono<User> asyncCapitalizeUser(User u) {
return Mono.just(
new User(u.getUsername().toUpperCase(),
u.getFirstname().toUpperCase(),
u.getLastname().toUpperCase()));
}
My implementation:
return flux
.map(user -> asyncCapitalizeUser(user))
.flatMap(Mono::flux)
Is this correct, and can it be improved?
Just this is enough:
return flux
.flatMap(this::asyncCapitalizeUser);
/**
* Transform the elements emitted by this {#link Flux} asynchronously into Publishers,
* then flatten these inner publishers into a single {#link Flux} through merging,
* which allow them to interleave.
* <p>
* There are three dimensions to this operator that can be compared with
* {#link #flatMapSequential(Function) flatMapSequential} and {#link #concatMap(Function) concatMap}:
* <ul>
* <li><b>Generation of inners and subscription</b>: this operator is eagerly
* subscribing to its inners.</li>
* <li><b>Ordering of the flattened values</b>: this operator does not necessarily preserve
* original ordering, as inner element are flattened as they arrive.</li>
* <li><b>Interleaving</b>: this operator lets values from different inners interleave
* (similar to merging the inner sequences).</li>
* </ul>
* <p>
* <img class="marble" src="https://raw.githubusercontent.com/reactor/reactor-core/v3.1.0.M3/src/docs/marble/flatmap.png" alt="">
* <p>
* #param mapper the {#link Function} to transform input sequence into N sequences {#link Publisher}
* #param <R> the merged output sequence type
*
* #return a new {#link Flux}
*/
public final <R> Flux<R> flatMap(Function<? super T, ? extends Publisher<? extends R>> mapper) {

How to generate Model/Example value section for GET request in Swagger

I am concerned on generating Model/Example value section for my GET request with Swagger.
The link to official example shows that section perfectly.
In official docs it is generated using existing model:
* #SWG\Schema(ref="#/definitions/User")
I don't have such an option, because my properties is generated by REST.
I have tried the following way:
/**
* #SWG\Get(
...
* #SWG\Response(
* response="200",
* description="Ok",
* #SWG\Schema(
* type="array",
* #SWG\Property(property="firstname", type="string", example="Steven")
* ),
* ),
* )
*/
It is not working and answers:
fetching resource list: http://localhost/dist/swagger.json; Please wait.
Any help is highly appreciated. Thanks in advance.
The GET /pet/findByStatus is generated in one of the examples:
github.com/zircote/swagger-php/.../Examples/petstore.swagger.io/controllers/PetController.php
The reason your snippet isn't working is because you're adding a property to an array type, which isn't supported.
To describe the contents of the array you'll need the #SWG\Items annotation:
...
* #SWG\Schema(
* type="array",
* #SWG\Items(
* type="object",
* #SWG\Property(property="firstname", type="string", example="Steven")
* )
* ),
...

How to get back to previous state after applying a matrix on a image?

I am using Fabricjs where I am applying some image filters using their convolute.
But it is very slower on image size more than 200KB.
Hence, I decided to write my own logic to apply filters and then to call canvas.renderAll() to update the canvas from the image canvas.
I am able to apply emboss using kernel
matrix: [ -2, -1, 0,
-1, 1, 1,
0, 1, 2 ]
But How to get back to original state of image ,In other words , do I need to apply any other kernel/matrix?
First of all write your own filter class:
(function(global) {
'use strict';
var fabric = global.fabric || (global.fabric = { }),
extend = fabric.util.object.extend;
fabric.Image.filters.MyFilter = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** #lends fabric.Image.filters.MyFilter.prototype */ {
/**
* Filter type
* #param {String} type
* #default
*/
type: 'MyFilter',
/**
* Constructor
*/
initialize: function(options) {
options = options || { };
},
/**
* Applies filter to canvas element
* #param {Object} canvasEl Canvas element to apply filter to
*/
applyTo: function(canvasEl) {
var context = canvasEl.getContext('2d'),
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
data = imageData.data,
for (var i = 0, len = data.length; i < len; i += 4) {
data[i] = 255 - data[i];
data[i + 1] = 255 - data[i + 1];
data[i + 2] = 255 - data[i + 2];
}
context.putImageData(imageData, 0, 0);
},
/**
* Returns object representation of an instance
* #return {Object} Object representation of an instance
*/
toObject: function() {
return extend(this.callSuper('toObject'), {
});
}
});
/**
* Returns filter instance from an object representation
* #static
* #param {Object} object Object to create an instance from
* #return {fabric.Image.filters.RemoveWhite} Instance of fabric.Image.filters.MyFilter
*/
fabric.Image.filters.MyFilter.fromObject = function(object) {
return new fabric.Image.filters.MyFilter(object);
};
})(typeof exports !== 'undefined' ? exports : this);
Second, apply the filter with your normal fabricjs logic:
myimage.filters[0] = new fabric.Image.filters.MyFilter;
myimage.applyFilters(canvas.renderAll.bind(canvas));
When you want to go back to normal image do:
myimage.filters[0] = null;
myimage.applyFilters(canvas.renderAll.bind(canvas));
Some considerations:
1) if the code you posted is your filter, it looks like an invert colors filter available at:
fabric.Image.filters.Invert()
2) if you really want to invert the formula again, you just need to run the filter again if you want to use a custom function.
if a = 255 - a, doing again a = 255 - a will revert to a original value.
3) some filter are not invertible, and if they are is better to store a copy of the image other than going back pixel by pixel.

How to correctly annotate this function for swagger?

I am trying to write a little Api using Slim. I want to have it documented very well so I installed swagger-php and UI and investigated on it the last days. For some reason my petstore demo is missing all the post annotations. My API will look like in this example:
http://coenraets.org/blog/2011/12/restful-services-with-jquery-php-and-the-slim-framework/
How would the swagger annotations for the addWine() function look like?
How do I annotate the result of the function (last insert id), since it is no model ?
An example would be really great.
Thank you
This would do it. Propably not ment to be like this, but doing exactly what I wanted.
/**
* #package
* #category
* #subpackage
*
* #SWG\Resource(
* apiVersion="1.0.0",
* swaggerVersion="1.2",
* basePath="http://myapi",
* resourcePath="/hello",
* description="Giving you your name in case you forgot it",
* produces="['application/json','application/xml','text/plain','text/html']"
* )
*/
/**
* #SWG\Api(
* path="/hello/{yourname}",
* #SWG\Operation(
* method="GET",
* summary="Gives you your name",
* notes="Returns your name",
* type="hello",
* nickname="yourname",
* #SWG\Parameter(
* name="yourname",
* description="Enter your name",
* required=true,
* type="text",
* paramType="path"
* ),
* #SWG\ResponseMessage(code=404, message="Bad, really bad name.")
* )
* )
*
*/
/**
* #package
* #category
* #subpackage
*
* #SWG\Model(id="hello",required="name")
*/
/**
* #SWG\Property(name="name",type="string",description="Your name")
*/

Resources