Tuesday, January 5, 2016

WordPress - add_tag_class() vs preg_replace()

If you got this error/warning:

Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in functions.php on line 209

preg_replace with /e modifier was deprecated in version 5.5:

http://php.net/manual/en/migration55.deprecated.php

"The preg_replace() /e modifier is now deprecated. Instead, use the preg_replace_callback() function."

Looking the documentation:

http://php.net/manual/en/function.preg-replace-callback.php

Then change this:

$regex = "#(.*tag-link[-])(.*)(' title.*)#e";

To this:

$regex = "#(.*tag-link[-])(.*)(' title.*)#";

And change this:

$tagn[] = preg_replace($regex, "('$1$2 label tag-'.get_tag($2)->slug.'$3')", $tag );

To this:

$tagn[] = preg_replace_callback($regex,
    function ($matches) {
        return $matches[1].$matches[2] ." label tag-". get_tag($matches[2])->slug . $matches[3];
    }, $tag);

Cheers!

Thursday, December 6, 2012

PHP + OpenOffice|LibreOffice = EXCEL & PDF Generator

To use OpenOffice from command-line to convert files is like this:

soffice -invisible -convert-to xls myfile.xml

In this case convert a xml file to xls. If you want a PDF file just change to:

soffice -invisible -convert-to pdf myfile.doc

You can use any kind of files supported by OpenOffice as input, and can define the parameter -convert-to to any format supported by Open Office.

I will now just talk about xml to xls, because is very most trick. And to PDF is simple like that above, nothing more to say about it.

To generate a xml valid to Open Office is not easy because the character encode, in my case portuguese iso-8859-15. I had a nightmare, but at end was more simple than seemed.

I save my data in DB utf8_encode then I have to use this function stringToExcelXML to decode and convert to XML special characters format.

Below my PHP code that build the XML compatible with OpenOffice and MSOffice:


error_reporting(E_ALL);
include '../include/config.php';

try {
 $rows = MySQL::Create('SELECT * FROM `Client` WHERE `Name` LIKE ?name ORDER BY `Name`')
  ->Parameter('name', '%'.$_GET['name'].'%', 'string')
  ->Query();
} catch(MySQLException $ex) {
 echo $ex->getMessage();
}

$outputFileName = 'export_'. date ('Ymd_His');

function stringToExcelXML($string){
    $string = htmlspecialchars(utf8_decode($string));
    $string = str_replace("\x01", "\x20", $string);
    return $string;
}

$f = fopen('../export/'. $outputFileName .'.xml', "w");
fwrite($f, '<?xml version="1.0" encoding="iso-8859-15"?>'. chr(13));
fwrite($f, '<?mso-application progid="Excel.Sheet"?>'. chr(13));
fwrite($f, '<Workbook');
fwrite($f, '   xmlns="urn:schemas-microsoft-com:office:spreadsheet"');
fwrite($f, '   xmlns:o="urn:schemas-microsoft-com:office:office"');
fwrite($f, '   xmlns:x="urn:schemas-microsoft-com:office:excel"');
fwrite($f, '   xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"');
fwrite($f, '   xmlns:html="http://www.w3.org/TR/REC-html40">'. chr(13));
fwrite($f, '  <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">'. chr(13));
fwrite($f, '    <Author>Candidatures</Author>'. chr(13));
fwrite($f, '    <LastAuthor>Candidatures</LastAuthor>'. chr(13));
fwrite($f, '    <Created>'. date('Y-m-d\TH:i:s\Z') .'</Created>'. chr(13));
fwrite($f, '    <Company>Candidatures</Company>'. chr(13));
fwrite($f, '    <Version>1</Version>'. chr(13));
fwrite($f, '  </DocumentProperties>'. chr(13));
fwrite($f, '  <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">'. chr(13));
fwrite($f, '    <WindowHeight>6795</WindowHeight>'. chr(13));
fwrite($f, '    <WindowWidth>8460</WindowWidth>'. chr(13));
fwrite($f, '    <WindowTopX>120</WindowTopX>'. chr(13));
fwrite($f, '    <WindowTopY>15</WindowTopY>'. chr(13));
fwrite($f, '    <ProtectStructure>False</ProtectStructure>'. chr(13));
fwrite($f, '    <ProtectWindows>False</ProtectWindows>'. chr(13));
fwrite($f, '  </ExcelWorkbook>'. chr(13));
fwrite($f, '  <Styles>'. chr(13));
fwrite($f, '    <Style ss:ID="Default" ss:Name="Normal">'. chr(13));
fwrite($f, '      <Alignment ss:Vertical="Bottom" />'. chr(13));
fwrite($f, '      <Borders />'. chr(13));
fwrite($f, '      <Font />'. chr(13));
fwrite($f, '      <Interior />'. chr(13));
fwrite($f, '      <NumberFormat />'. chr(13));
fwrite($f, '      <Protection />'. chr(13));
fwrite($f, '    </Style>'. chr(13));
fwrite($f, '    <Style ss:ID="s21">'. chr(13));
fwrite($f, '      <Font x:Family="Swiss" ss:Bold="1" />'. chr(13));
fwrite($f, '    </Style>'. chr(13));
fwrite($f, '  </Styles>'. chr(13));
fwrite($f, '  <Worksheet ss:Name="Clients">'. chr(13));
fwrite($f, '    <Table ss:ExpandedColumnCount="2" ss:ExpandedRowCount="'. (isset($rows) ? count($rows) : 0) .'"');
fwrite($f, '         x:FullColumns="1" x:FullRows="1">'. chr(13));
fwrite($f, '      <Row>'. chr(13));
fwrite($f, '        <Cell ss:StyleID="s21">'. chr(13));
fwrite($f, '          <Data ss:Type="String">Id</Data>'. chr(13));
fwrite($f, '        </Cell>'. chr(13));
fwrite($f, '        <Cell ss:StyleID="s21">'. chr(13));
fwrite($f, '          <Data ss:Type="String">Name</Data>'. chr(13));
fwrite($f, '        </Cell>'. chr(13));
fwrite($f, '      </Row>'. chr(13));
if (isset($rows)) {
  foreach($rows as $row) {
    fwrite($f, '      <Row>'. chr(13));
    fwrite($f, '        <Cell ss:StyleID="s21">'. chr(13));
    fwrite($f, '          <Data ss:Type="String">'. $row['Id'] .'</Data>'. chr(13));
    fwrite($f, '        </Cell>'. chr(13));
    fwrite($f, '        <Cell ss:StyleID="s21">'. chr(13));
    fwrite($f, '          <Data ss:Type="String">'. stringToExcelXML($row['Name']) .'</Data>'. chr(13));
    fwrite($f, '        </Cell>'. chr(13));
    fwrite($f, '      </Row>'. chr(13));
  }
}
fwrite($f, '    </Table>'. chr(13));
fwrite($f, '    <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">'. chr(13));
fwrite($f, '      <Print>'. chr(13));
fwrite($f, '        <ValidPrinterInfo />'. chr(13));
fwrite($f, '        <HorizontalResolution>600</HorizontalResolution>'. chr(13));
fwrite($f, '        <VerticalResolution>600</VerticalResolution>'. chr(13));
fwrite($f, '      </Print>'. chr(13));
fwrite($f, '      <Selected />'. chr(13));
fwrite($f, '      <Panes>'. chr(13));
fwrite($f, '        <Pane>'. chr(13));
fwrite($f, '          <Number>3</Number>'. chr(13));
fwrite($f, '          <ActiveRow>5</ActiveRow>'. chr(13));
fwrite($f, '          <ActiveCol>1</ActiveCol>'. chr(13));
fwrite($f, '        </Pane>'. chr(13));
fwrite($f, '      </Panes>'. chr(13));
fwrite($f, '      <ProtectObjects>False</ProtectObjects>'. chr(13));
fwrite($f, '      <ProtectScenarios>False</ProtectScenarios>'. chr(13));
fwrite($f, '    </WorksheetOptions>'. chr(13));
fwrite($f, '  </Worksheet>'. chr(13));

fclose($f);

$excelFile = '../export/'. $outputFileName .'.xls';

while (true) {
  sleep(1);
  if (file_exists($excelFile)) {
    sleep(100);
    break;
  }
}

header('Content-Disposition: attachment; filename='. $outputFileName .'.xls');
header('Content-Type: application/octet-stream');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-length: '. filesize($excelFile));
ob_clean();
flush();
readfile($excelFile);
unlink($excelFile);

exit();
?>

Attention with worksheet name <Worksheet ss:Name="Clients"> and the number of columns <Table ss:ExpandedColumnCount="2" ... and the encoding="iso-8859-15".

This block of code below will wait the OpenOffice finish the creation of file XLS.

$excelFile = '../export/'. $outputFileName .'.xls';

while (true) {
  sleep(1);
  if (file_exists($excelFile)) {
    sleep(100);
    break;
  }
}

This service made with shell script need still running all time to build XLSs using OpenOffice:

/var/www/services/openoffice_to_xls/openoffice_to_xls.sh
#!/bin/bash

cd /var/www/htdocs/export

while true
do
  for f in `ls *.xml`
  do
    sleep 1
    echo "$f"
    soffice -invisible -convert-to xls "$f"
    sleep 15
    chmod a+rwx *.xls
    rm -f "$f"
  done
  sleep 1
done

Turn the core.sh file as executable:

chmod +x /var/www/services/openoffice_to_xls/core.sh

A start script will be useful:

/var/www/services/openoffice_to_xls/start.sh
#!/bin/bash

rm -f /var/www/services/openoffice_to_xls/nohup.out
nohup /var/www/services/openoffice_to_xls/core.sh &

Turn the start.sh file as executable:

chmod +x /var/www/services/openoffice_to_xls/start.sh

Now just start the service:

/var/www/services/openoffice_to_xls/start.sh

All of this is very trick and to works with MSOffice 2010 and OpenXML... and to this work exists the PHPExcel that is much more elegant:

phpexcel.codeplex.com

But to build office legacy files perhaps these tricks will be useful to do workarounds.

Have fun and good nightmares.

Friday, March 25, 2011

Resolve the IP Number from a Host Name

This sample translate the IP number from www.google.com. But you can even use localhost or localmachinename to gets the local or external IP number of the local machine.

#include <stdio.h>
#include <iostream>
#include <arpa/inet.h>
#include <netdb.h>
int main() {
  char hostName[] = "www.google.com";
  struct hostent *host;
  if ((host = gethostbyname(hostName)) == NULL) {
    fprintf(stderr, "(mini) nslookup failed on '%s'", hostName);
    return 1;
  }
  struct in_addr h_addr;
  h_addr.s_addr = *((unsigned long *) host->h_addr_list[0]);
  const char *ip = inet_ntoa(h_addr);
  std::cout << ip << std::endl;
  return 0;
}

Convert Integer to String without itoa

This solution is based from here.

#include <iostream>
#include <sstream>
int main() {
  int i = 100;
  std::stringstream ss;
  ss << i;
  fprintf(stderr, ss.str().c_str());
}

GNU/C++ Simple Send Mail

See the Microsoft Visual C++ Simple Send Mail here.

I did the class below for GNU C++ based in these links:

SendMail.h:

#ifndef _SENDMAILHEADER
#define _SENDMAILHEADER

#include <sys/socket.h>
#include <arpa/inet.h>
#include <string>
#include <string.h>

#define HELO "HELO\r\n"
#define DATA "DATA\r\n"
#define QUIT "QUIT\r\n"

namespace mail {
class SendMail {
private:
int sock;
char buf[BUFSIZ];
void send_socket(char *s)
{
send(sock, s, strlen(s), 0);
//fprintf(stderr, s);
}
void read_socket()
{
int len = recv(sock, buf, BUFSIZ, 0);
//fprintf(stderr, ((std::string)buf).substr(0, len).c_str());
}
public:
char* HostIp;
unsigned short HostPort;
char* To;
char* From;
char* Subject;
char* Message;
SendMail() {
HostPort = 25;
};
~SendMail() { };
void Send() {
struct sockaddr_in hostAddr;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
fprintf(stderr, "SendMail: socket() failed");
return;
}
hostAddr.sin_family = AF_INET;
hostAddr.sin_addr.s_addr = inet_addr(HostIp);
hostAddr.sin_port = htons(HostPort);
if (connect(sock, (struct sockaddr *) &hostAddr, sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "SendMail: connect() failed");
return;
}
read_socket();
send_socket((char*)HELO);
read_socket();
send_socket((char*)"MAIL FROM: ");
send_socket(From);
send_socket((char*)"\r\n");
read_socket();
send_socket((char*)"VRFY ");
send_socket(From);
send_socket((char*)"\r\n");
read_socket();
send_socket((char*)"RCPT TO: ");
send_socket(To);
send_socket((char*)"\r\n");
read_socket();
send_socket((char*)DATA);
send_socket((char*)"Subject: ");
send_socket(Subject);
send_socket((char*)"\r\n");
read_socket();
send_socket(Message);
send_socket((char*)"\r\n");
send_socket((char*)".\r\n");
read_socket();
send_socket((char*)QUIT);
read_socket();
close(sock);
};
};
}

#endif


Usage:

#include "SendMail.h"

int main(int argc, char** argv) {
mail::SendMail* sendmail = new mail::SendMail();
sendmail->HostIp = (char*)"192.168.1.10";
sendmail->From = (char*)"mail@address.com";
sendmail->To = (char*)"mail@address.com";
sendmail->Subject = (char*)"Test!";
sendmail->Message = (char*)"Content:\nTest 123...";
sendmail->Send();
return 0;
}

VC++ Simple Send Mail

See the GNU/C++ Simple Send Mail here.

I did the class below for Visual C++ based in these links:

SendMail.h:

#ifndef _SENDMAILHEADER
#define _SENDMAILHEADER

#include "stdafx.h"
#include <stdio.h>
#include <Winsock2.h>
#include <Windows.h>
#include <string>

#pragma comment(lib, "ws2_32.lib")

#define HELO "HELO\r\n"
#define DATA "DATA\r\n"
#define QUIT "QUIT\r\n"

namespace mail {
class SendMail {
private:
int sock;
char buf[BUFSIZ];
void send_socket(char *s)
{
send(sock, s, strlen(s), 0);
//fprintf(stderr, s);
}
void read_socket()
{
int len = recv(sock, buf, BUFSIZ, 0);
//fprintf(stderr, ((std::string)buf).substr(0, len).c_str());
}
public:
char* HostIp;
unsigned short HostPort;
char* To;
char* From;
char* Subject;
char* Message;
SendMail() {
HostPort = 25;
};
~SendMail() { };
void Send() {
struct sockaddr_in hostAddr;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
fprintf(stderr, "SendMail: WSAStartup() failed");
return;
}
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
fprintf(stderr, "SendMail: socket() failed");
return;
}
memset(&hostAddr, 0, sizeof(hostAddr));
hostAddr.sin_family = AF_INET;
hostAddr.sin_addr.s_addr = inet_addr(HostIp);
hostAddr.sin_port = htons(HostPort);
if (connect(sock, (struct sockaddr *) &hostAddr, sizeof(hostAddr)) < 0) {
fprintf(stderr, "SendMail: connect() failed");
return;
}
read_socket();
send_socket(HELO);
read_socket();
send_socket("MAIL FROM: ");
send_socket(From);
send_socket("\r\n");
read_socket();
send_socket("VRFY ");
send_socket(From);
send_socket("\r\n");
read_socket();
send_socket("RCPT TO: ");
send_socket(To);
send_socket("\r\n");
read_socket();
send_socket(DATA);
send_socket("Subject: ");
send_socket(Subject);
send_socket("\r\n");
read_socket();
send_socket(Message);
send_socket("\r\n");
send_socket(".\r\n");
read_socket();
send_socket(QUIT);
read_socket();
closesocket(sock);
WSACleanup();
};
};
}

#endif


Usage:

#include "stdafx.h"
#include "SendMail.h"

int main(int argc, char* argv[])
{
mail::SendMail* sendmail = new mail::SendMail();
sendmail->HostIp = "192.168.1.10";
sendmail->From = "mail@address.com";
sendmail->To = "mail@address.com";
sendmail->Subject = "Test!";
sendmail->Message = "Content:\nTest 123...";
sendmail->Send();
return 0;
}

Friday, September 17, 2010

Force JPA load Identity ID after Insert

When you have an ID into your Entity Classe from Database and that is Identity, if you do an insert action the ID of this Entity isn't reloaded by default with the ID that was generated by Database, through JPA.

A sample of an ID of Identity kind:

@Id
@Basic(optional = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "Id")
private Integer id;


To refresh the ID value with the ID that was generated by the Database on insert action, you need put more this below in your AbstractFacade.Create(EntityClass):

getEntityManager().flush();
getEntityManager().refresh(entity);


  • getEntityManager().flush() - Will do the commit to Database execute the insert action.

  • getEntityManager().refresh(entity) - Will refresh the entity object with a new ID that was inserted.


Full sample of the AbstractFacade.java:

package org.test.ejb;

import java.util.List;
import javax.persistence.EntityManager;

public abstract class AbstractFacade {
private Class entityClass;

public AbstractFacade(Class entityClass) {
this.entityClass = entityClass;
}

protected abstract EntityManager getEntityManager();

public void create(T entity) {
getEntityManager().persist(entity);
getEntityManager().flush();
getEntityManager().refresh(entity);
}

public void edit(T entity) {
getEntityManager().merge(entity);
}

public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}

public T find(Object id) {
return getEntityManager().find(entityClass, id);
}

public List findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}

public List findRange(int[] range) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
javax.persistence.Query q = getEntityManager().createQuery(cq);
q.setMaxResults(range[1] - range[0]);
q.setFirstResult(range[0]);
return q.getResultList();
}

public int count() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
javax.persistence.criteria.Root rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
javax.persistence.Query q = getEntityManager().createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
}
}


If you publish your JPA Create action in a Web Services, you will need return to client side an Entity instance to client know what is the new ID. Cause the Entity instance of the Client side can't be refresh with changes inside Server.
Like:

@WebMethod(operationName = "create")
public BusinessEntity create(@WebParam(name = "businessEntity")
BusinessEntity businessEntity) {
ejbRef.create(businessEntity);
return businessEntity;
}