Friday, May 5, 2017

Connect to Xero Private Application Using Php Application

The link below is for Xero dashboard:
https://my.xero.com

Very first you need to create an application in Xero, follow the link below to create application:
https://app.xero.com/Application/

Click on "Add Application" and fill up required fields. In this step you will need public/private key pair. To generate public/pair key follow the link. You need to upload "publickey.cer" in xero application form and other file named "privatekey.perm" need to place in a folder named "XeroCerts" in your application directory.




After click save you will forward to next page, from where you can get Consumer Key & Consumer Secret which will need to connect to your organization via this application.





You are done with create application in Xero.

Next step to write some PHP script to connect to Xero.
Below is a small PHP script which help you to connect to Xero.


<?php
define('BASE_PATH', dirname(__FILE__));
$configs = array(
    "consumer_key" => "QM6QQSESK2KVGTRUGY1........",
    "consumer_secret" => "LHAHIPRIIP6ZZASIHPP........",
    "core_version" => "2.0",
    "payroll_version" => "1.0",
    "file_version" => "1.0",
    "rsa_private_key" => BASE_PATH . "/XeroCerts/privatekey.pem",
    "rsa_public_key" => BASE_PATH . "/XeroCerts/publickey.cer",
    "application_type" => "Private",
    "oauth_callback" => "oob",
    "user_agent" => "Trial #3"
);

$parameters = array();

$xero_connector = new XeroConnector($configs, $parameters);
$organization_data = $xero_connector->execute("GET", "Organisation");
XeroConnector::prettyPrint($organization_data);

class XeroConnector
{
    private $configs = null;
    private $headers = array();
    private $parameters = array();

    function __construct($configs, $parameters)
    {
        $this->configs = $configs;
        $this->parameters = $parameters;
    }

    function execute($method, $target, $post_body = "")
    {
        $this->post_body = $post_body;
        $this->method = strtoupper($method);
        $this->path = "https://api.xero.com/api.xro/2.0/$target";
        $this->nonce_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        $this->buildParameters();
        $this->sign();
        return $this->curlRequest($this->sign["signed_url"]);
    }

    private function sign()
    {
        $this->parameters["oauth_signature"] = $this->generateSignature();
        $this->sign = array(
            'parameters' => $this->parameters,
            'signature' => $this->escape($this->parameters["oauth_signature"]),
            'signed_url' => $this->path . '?' . $this->normalizeParameters('true'),
            'header' => $this->getHeaderString(),
            'sbs' => $this->sbs
        );
    }

    private function curlRequest($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        $this->headers['Accept'] = 'application/json';
        switch ($this->method) {
            case "GET":
                $this->content_length = 0;
                break;
            case 'POST':
                $this->headers['Content-Length'] = strlen($this->post_body);
                curl_setopt($ch, CURLOPT_POST, TRUE);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $this->post_body);
                $this->headers['Content-Type'] = 'application/x-www-form-urlencoded';
                break;
            case 'PUT' :
                $this->headers['Content-Length'] = strlen($this->post_body);
                $fh = tmpfile();
                fwrite($fh, $this->post_body);
                rewind($fh);
                curl_setopt($ch, CURLOPT_PUT, true);
                curl_setopt($ch, CURLOPT_INFILE, $fh);
                curl_setopt($ch, CURLOPT_INFILESIZE, $this->headers ['Content-Length']);
                $this->headers['Content-Type'] = 'application/x-www-form-urlencoded';
                break;
            default :
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);
        }

        if (count($this->headers) > 0) {
            $headers = array();
            foreach ($this->headers as $k => $v) {
                $headers [] = trim($k . ': ' . $v);
            }
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        $response = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        curl_close($ch);

        return array('body' => json_decode($response), 'code' => $code);
    }

    private function getHeaderString($args = array())
    {
        $result = 'OAuth ';

        foreach ($this->parameters as $pName => $pValue) {
            if (strpos($pName, 'oauth_') !== 0)
                continue;
            if (is_array($pValue)) {
                foreach ($pValue as $val) {
                    $result .= $pName . '="' . $this->escape($val) . '", ';
                }
            } else {
                $result .= $pName . '="' . $this->escape($pValue) . '", ';
            }
        }
        return preg_replace('/, $/', '', $result);
    }

    private function generateSignature()
    {
        switch ($this->parameters['oauth_signature_method']) {
            case 'RSA-SHA1':
                $private_key = openssl_pkey_get_private($this->readFile($this->configs['rsa_private_key']));
                $this->sbs = $this->escape($this->method) . "&" . $this->escape($this->path) . "&" .
                    $this->escape($this->normalizeParameters());
                openssl_sign($this->sbs, $signature, $private_key);
                openssl_free_key($private_key);
                return base64_encode($signature);
            case 'PLAINTEXT':
                return urlencode($this->configs["consumer_secret"]);
            case 'HMAC-SHA1':
                $this->sbs = $this->escape($this->method) . '&' . $this->escape($this->path) . '&' . $this->escape($this->normalizeParameters());
                return base64_encode(hash_hmac('sha1', $this->sbs, $this->configs["consumer_secret"], true));
            default:
                throw new OAuthSimpleException('Unknown signature method for OAuthSimple');
        }
    }

    private function normalizeParameters($filter = 'false')
    {
        $elements = array();
        ksort($this->parameters);
        foreach ($this->parameters as $paramName => $paramValue) {
            if ($paramName == 'xml') {
                if ($filter == "true")
                    continue;
            }
            if (preg_match('/\w+_secret/', $paramName))
                continue;
            if (is_array($paramValue)) {
                sort($paramValue);
                foreach ($paramValue as $element)
                    array_push($elements, $this->escape($paramName) . '=' . $this->escape($element));
                continue;
            }
            array_push($elements, $this->escape($paramName) . '=' . $this->escape($paramValue));

        }
        return join('&', $elements);
    }

    private function readFile($file_path)
    {
        $fp = fopen($file_path, "r");
        $file_contents = fread($fp, 8192);
        fclose($fp);
        return $file_contents;
    }

    private function escape($string)
    {
        if ($string === 0)
            return 0;
        if (empty($string))
            return '';
        if (is_array($string))
            throw new OAuthSimpleException('Array passed to _oauthEscape');

        $string = rawurlencode($string);
        $string = str_replace('+', '%20', $string);
        $string = str_replace('!', '%21', $string);
        $string = str_replace('*', '%2A', $string);
        $string = str_replace('\'', '%27', $string);
        $string = str_replace('(', '%28', $string);
        $string = str_replace(')', '%29', $string);
        return $string;
    }

    private function buildParameters()
    {
        $this->parameters["oauth_nonce"] = $this->getNonce(5);
        $this->parameters["oauth_token"] = $this->configs["consumer_key"];
        $this->parameters["oauth_version"] = "1.0";
        $this->parameters["oauth_timestamp"] = time();
        $this->parameters["oauth_consumer_key"] = $this->configs["consumer_key"];
        $this->parameters["oauth_signature_method"] = "RSA-SHA1";
    }

    private function getNonce($length = 5)
    {
        $result = '';
        $cLength = strlen($this->nonce_chars);
        for ($i = 0; $i < $length; $i++) {
            $rnum = rand(0, $cLength);
            $result .= substr($this->nonce_chars, $rnum, 1);
        }
        return $result;
    }

    public static function prettyPrint($o)
    {
        echo "<pre>";
        print_r($o);
        echo "</pre>";
    }
}


And output will be like this on execution the above script:


Array
(
    [body] => stdClass Object
        (
            [Id] => 0d1fe562-8621-4bbb-b249-6a5ea051f308
            [Status] => OK
            [ProviderName] => Trial #3
            [DateTimeUTC] => /Date(1494001316337)/
            [Organisations] => Array
                (
                    [0] => stdClass Object
                        (
                            [APIKey] => W2N0UZYHPLFSPABKS2SS42AF5GDKMD
                            [Name] => Trial #3
                            [LegalName] => Trial #3
                            [PaysTax] => 1
                            [Version] => AU
                            [OrganisationType] => COMPANY
                            [BaseCurrency] => AUD
                            [CountryCode] => AU
                            [IsDemoCompany] => 
                            [OrganisationStatus] => ACTIVE
                            [FinancialYearEndDay] => 30
                            [FinancialYearEndMonth] => 6
                            [SalesTaxBasis] => ACCRUALS
                            [SalesTaxPeriod] => QUARTERLY1
                            [DefaultSalesTax] => Tax Exclusive
                            [DefaultPurchasesTax] => Tax Inclusive
                            [CreatedDateUTC] => /Date(1493991850000)/
                            [OrganisationEntityType] => COMPANY
                            [Timezone] => AUSEASTERNSTANDARDTIME
                            [ShortCode] => !GS3w5
                            [OrganisationID] => c653628f-a901-4836-8de1-6b00d23664fe
                            [LineOfBusiness] => Software Development & Consulting
                            [Addresses] => Array
                                (
                                )

                            [Phones] => Array
                                (
                                )

                            [ExternalLinks] => Array
                                (
                                )

                            [PaymentTerms] => stdClass Object
                                (
                                )

                        )

                )

        )

    [code] => 200
)



Create public/private key pair using OAuth RSA-SHA1 method on Windows with OpenSSL

Download OpenSSL from http://slproweb.com/products/Win32OpenSSL.html
And install on your machine.

Or you can download light version from windows 32 bit from here.
Or you can download light version from windows 64 bit from here.

Open Command Prompt as Administrator and navigate to "C:\OpenSSL-Win32\bin". (Assumed that in that location your openssl installed)

Now execute the following three commands:

openssl genrsa -out privatekey.pem 1024

set OPENSSL_CONF=C:/OpenSSL-Win32/bin/openssl.cfg [It may  be .cfg or .cnf, check your bin directory]

openssl req -new -x509 -key privatekey.pem -out publickey.cer -days 1825

Below are two screen-shots:




Friday, April 28, 2017

jQuery UI Sortable and Draggable NOT working on iPad, iPhone or Android

jQuery UI sortable, draggable, re-sizable and all others working fine on browsers with no problems, however when I test it on hand held devices such as iPad, iPod, iPhone and Android it doesn't work. I cannot drag the boxes or sort the order at all.

Touch Punch will fix this issue, and most other jQuery UI on touch device problems. They described the process as hack, but it it is a lifesaver too.

Also you can download library from here.

Saturday, April 22, 2017

Generate PDF in CakePHP 3.x with CakePDF And DomPDF

At first you need to install CakePDF to your project. Add "friendsofcake/cakepdf": "3.2.*" to "composer.json" file under "require" section as follows:

"require": {

    "friendsofcake/cakepdf": "3.2.*"

}

Now open command panel and navigate to project directory and execute:

composer update friendsofcake/cakepdf --lock


Or you can direct execute the command "composer require friendsofcake/cakepdf" to install CakePDF. This command will install a suitable latest version to your project.


Above command will install CakePDF to your project.


Next step is to install DomPDF.


Execute following command to install DomPDF
"composer require dompdf/dompdf".


Installation complete, now add the following line to "config/bootstrap.php" file:


Plugin::load('CakePdf', ['bootstrap' => true]);


Configure::write('CakePdf', [

    'engine' => [
        'className' => 'CakePdf.Dompdf',
        'options' => [
            'print-media-type' => false,
            'outline' => true,
            'dpi' => 96
        ]
    ],
    'pageSize' => 'Letter',
]);
define('DOMPDF_ENABLE_AUTOLOAD', false);
define('DOMPDF_ENABLE_HTML5PARSER', true);
define('DOMPDF_ENABLE_REMOTE', true);


Configuration options:
  • engine: Engine to be used (required), or an array of engine config options
    • className: Engine class to use
    • options: Engine specific options. Currently only for WkHtmlToPdf, where the options are passed as CLI arguments, and for DomPdf, where the options are passed to the DomPdf class constructor.
  • crypto: Crypto engine to be used, or an array of crypto config options
    • className: Crypto class to use
    • binary: Binary file to use
  • pageSize: Change the default size, defaults to A4
  • orientation: Change the default orientation, defaults to portrait
  • margin: Array or margins with the keys: bottom, left, right, top and their values
  • title: Title of the document
  • delay: A delay in milliseconds to wait before rendering the pdf
  • windowStatus: The required window status before rendering the PDF
  • encoding: Change the encoding, defaults to UTF-8
  • download: Set to true to force a download, only when using PdfView
  • filename: Filename for the document when using forced download

Now we can do 3 things with our CakePDF
1. Download PDF
2. Stream PDF to browser
3. Save PDF to our server

Lets go for download & stream PDF:

Add the following code block in "config/router.php" file:


Router::scope('/pdf_download/:id', function (RouteBuilder $routes) {

    $routes->addExtensions(['pdf']);
    $routes->connect('/', ['controller' => 'Pages', 'action' => 'cakePdfDownload']);

});

Now in your "PagesController.php" add below code snippet:


public function cakePdfDownload($name = null)

{
    Configure::write('CakePdf.download', true);
    Configure::write('CakePdf.filename', "MyCustomName.pdf");

}

Now need to create a layout file for pdf. Create "default.ctp" under "Template/Layout/Pdf" directory with following contents:


<?php

use Cake\Core\Configure;
$cakeDescription = 'CakePHP: the rapid development PHP framework';
?>
<!DOCTYPE html>
<html>
<head>
    <?= $this->Html->charset() ?>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
        <?= $cakeDescription ?>:
        <?= $this->fetch('title') ?>
    </title>

    <?= $this->Html->meta('icon') ?>

    <?= $this->Html->css('base.css', ['fullBase' => true]) ?>
    <?= $this->Html->css('cake.css', ['fullBase' => true]) ?>
    <?= $this->Html->css('home.css', ['fullBase' => true]) ?>
    <link href="https://fonts.googleapis.com/css?family=Raleway:500i|Roboto:300,400,700|Roboto+Mono" rel="stylesheet">
</head>
<body class="home">

<header class="row">

    <div class="header-image"><?= $this->Html->image('cake.logo.svg') ?></div>
    <div class="header-title">
        <h1>Welcome to CakePHP <?= Configure::version() ?> Red Velvet. Build fast. Grow solid.</h1>
    </div>
</header>
<div class="row">
    <div class="columns large-12">
        <?= $this->fetch('content') ?>
    </div>
</div>
</body>

</html>

'fullBase' => true for create permanent link to resources.


Now create a file named "cake_pdf_download.ctp" under "Template/Pages/Pdf" directory with any content.


You are done, you browse "http://localhost/cake/pdf_download/invoice.pdf" then a pdf will be downloaded because we set "Configure::write('CakePdf.download', true);" if we set false here as "Configure::write('CakePdf.download', false);" then PDF will not be downloaded but will be rendered in browser itself.






Now go for save PDF to our server:


public function cakePdf()

{
    $CakePdf = new \CakePdf\Pdf\CakePdf();
    $CakePdf->template('cake_pdf', 'default');
    $CakePdf->viewVars($this->viewVars);
    $pdf = $CakePdf->write(APP . 'Files' . DS . 'Output.pdf');
    echo $pdf;die();

}

And finally you are done CakePDF with DomPDF.

Friday, April 21, 2017

Generate PDFs in Laravel 5.x with Snappy & Wkhtmltopdf

At first we need to install Wkhtmltopdf on our server. To do so we need to add following lines under "require" section on composer.json file as follows:

For 32 bit server:



"require": {
    "h4cc/wkhtmltopdf-i386": "0.12.x",
    "h4cc/wkhtmltoimage-i386": "0.12.x"
}




And for 64 bit server:


"require": {
    "h4cc/wkhtmltopdf-amd64": "0.12.x",
    "h4cc/wkhtmltoimage-amd64": "0.12.x"
}


Now time to install wkhtmltopdf. Open command prompt and navigate to your project location and execute below command to install packages into your project:

composer update h4cc/wkhtmltopdf-i386 --lock
composer update h4cc/wkhtmltoimage-i386 --lock
Or you can download wkhtmltopdf from here. Or you can download also from here.

For windows you do not do anything above. Just download installer for windows version, install it in your machine, done. 

After installation done, need to install "Laravel-Snappy", to do so add following to "composer.json" as follows:


"require": {
    "barryvdh/laravel-snappy": "0.3.x"
}

Open command prompt and navigate to your project location and execute below command to install packages into your project:

composer update barryvdh/laravel-snappy --lock

Next step is to add the line "Barryvdh\Snappy\ServiceProvider::class" to file "config/app.php" under the section "providers" as follows:


'providers' => [Barryvdh\Snappy\ServiceProvider::class]

Its time to add an alias, do the following in "config/app.php" under "aliases" section:


'aliases' => [
    'SnappyPDF' => Barryvdh\Snappy\Facades\SnappyPdf::class
]

Now copy "vendor/barryvdh/laravel-snappy/config/snappy.php" file to "/config" folder and modify as follows:

Location of binary is your wkhtmltopdf installation location. You must careful with the path.

Binary path will be as follows:

For Linux Server with project location: "binary" => ...
base_path('vendor/h4cc/wkhtmltopdf-amd64/bin/wkhtmltopdf-amd64')

For Linux Server with fixed location: "binary" => ...
"/usr/local/bin/wkhtmltopdf-amd64"

And for Windows with installation location: "binary" => ...
'"C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf\bin\wkhtmltopdf.exe"'

<?php
return array(
    'pdf' => array(
        'enabled' => true,
        'binary'  => 'C:\PROGRA~1\wkhtmltopdf\bin\wkhtmltopdf.exe',
        'timeout' => false,
        'options' => array(),
        'env'     => array(),
    ),
    'image' => array(
        'enabled' => true,
        'binary'  => 'C:\PROGRA~1\wkhtmltopdf\bin\wkhtmltoimage.exe',
        'timeout' => false,
        'options' => array(),
        'env'     => array(),
    )

);

Execute following command:
php artisan vendor:publish

Below is a code snippet to stream pdf to browser:

<?php
namespace App\Http\Controllers;

use SnappyPDF;
use Illuminate\Routing\Controller as BaseController;

class HomeController extends BaseController
{
    public function pdf()
    {
        set_time_limit(60 * 5);
        $d1 = array();
        $d2 = array();

        $pdf = SnappyPDF::loadView('home.pdf', compact('d1', 'd2'));

        //Below line code will save pdf to "public" folder
        //$pdf->save('Output.pdf'); die();

        //Below line code to download pdf
        //return $pdf->download('Output.pdf');

        //Below line code will stream PDF to browser
        return $pdf->stream('Output.pdf');
    }

}

And thats it, you have integrated Wkhtmltopdf in your Laravel project using Snappy.

Generate PDF in CakePHP 3.x with CakePDF And Wkhtmltopdf

At first you need to install CakePDF to your project. Add "friendsofcake/cakepdf": "3.2.*" to "composer.json" file under "require" section as follows:

"require": {

    "friendsofcake/cakepdf": "3.2.*"

}

Now open command panel and navigate to project directory and execute:

composer update friendsofcake/cakepdf --lock


Or you can direct execute the command "composer require friendsofcake/cakepdf" to install CakePDF. This command will install a suitable latest version to your project.


Above command will install CakePDF to your project.


Next step is to install wkhtmltopdf.


Download wkhtmltopdf from https://wkhtmltopdf.org/downloads.html.


By default CakePdf expects the wkhtmltopdf binary to be located in /usr/bin/wkhtmltopdf. If you are using wkhtmltopdf in Windows, remove any spaces in the path name. For example use C:/Progra~1/wkhtmltopdf/bin/wkhtmltopdf.exe (Your installation location).



Installation complete, now add the following line to "config/bootstrap.php" file:


Plugin::load('CakePdf', ['bootstrap' => true]);


Configure::write('CakePdf', [

    'engine' => [
        'className' => 'CakePdf.WkHtmlToPdf',
        //'binary' => '/usr/bin/wkhtmltopdf', //LINUX
        'binary' => 'C:\PROGRA~1\wkhtmltopdf\bin\wkhtmltopdf.exe', //WINDOWS
        'options' => [
            'print-media-type' => false,
            'outline' => true,
            'dpi' => 96
        ]
    ],
    'pageSize' => 'Letter',
]);


Configuration options:
  • engine: Engine to be used (required), or an array of engine config options
    • className: Engine class to use
    • binary: Binary file to use (Only for wkhtmltopdf)
    • options: Engine specific options. Currently only for WkHtmlToPdf, where the options are passed as CLI arguments, and for DomPdf, where the options are passed to the DomPdf class constructor.
  • crypto: Crypto engine to be used, or an array of crypto config options
    • className: Crypto class to use
    • binary: Binary file to use
  • pageSize: Change the default size, defaults to A4
  • orientation: Change the default orientation, defaults to portrait
  • margin: Array or margins with the keys: bottom, left, right, top and their values
  • title: Title of the document
  • delay: A delay in milliseconds to wait before rendering the pdf
  • windowStatus: The required window status before rendering the PDF
  • encoding: Change the encoding, defaults to UTF-8
  • download: Set to true to force a download, only when using PdfView
  • filename: Filename for the document when using forced download

Now we can do 3 things with our CakePDF
1. Download PDF
2. Stream PDF to browser
3. Save PDF to our server

Lets go for download & stream PDF:

Add the following code block in "config/router.php" file:


Router::scope('/pdf_download/:id', function (RouteBuilder $routes) {

    $routes->addExtensions(['pdf']);
    $routes->connect('/', ['controller' => 'Pages', 'action' => 'cakePdfDownload']);

});

Now in your "PagesController.php" add below code snippet:


public function cakePdfDownload($name = null)

{
    Configure::write('CakePdf.download', true);
    Configure::write('CakePdf.filename', "MyCustomName.pdf");

}

Now need to create a layout file for pdf. Create "default.ctp" under "Template/Layout/Pdf" directory with following contents:


<?php

use Cake\Core\Configure;
$cakeDescription = 'CakePHP: the rapid development PHP framework';
?>
<!DOCTYPE html>
<html>
<head>
    <?= $this->Html->charset() ?>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
        <?= $cakeDescription ?>:
        <?= $this->fetch('title') ?>
    </title>

    <?= $this->Html->meta('icon') ?>

    <?= $this->Html->css('base.css', ['fullBase' => true]) ?>
    <?= $this->Html->css('cake.css', ['fullBase' => true]) ?>
    <?= $this->Html->css('home.css', ['fullBase' => true]) ?>
    <link href="https://fonts.googleapis.com/css?family=Raleway:500i|Roboto:300,400,700|Roboto+Mono" rel="stylesheet">
</head>
<body class="home">

<header class="row">

    <div class="header-image"><?= $this->Html->image('cake.logo.svg') ?></div>
    <div class="header-title">
        <h1>Welcome to CakePHP <?= Configure::version() ?> Red Velvet. Build fast. Grow solid.</h1>
    </div>
</header>
<div class="row">
    <div class="columns large-12">
        <?= $this->fetch('content') ?>
    </div>
</div>
</body>

</html>

'fullBase' => true for create permanent link to resources.


Now create a file named "cake_pdf_download.ctp" under "Template/Pages/Pdf" directory with any content.


You are done, you browse "http://localhost/cake/pdf_download/invoice.pdf" then a pdf will be downloaded because we set "Configure::write('CakePdf.download', true);" if we set false here as "Configure::write('CakePdf.download', false);" then PDF will not be downloaded but will be rendered in browser itself.






Now go for save PDF to our server:


public function cakePdf()

{
    $CakePdf = new \CakePdf\Pdf\CakePdf();
    $CakePdf->template('cake_pdf', 'default');
    $CakePdf->viewVars($this->viewVars);
    $pdf = $CakePdf->write(APP . 'Files' . DS . 'Output.pdf');
    echo $pdf;die();

}

And finally you are done CakePDF with wkhtmltopdf.

Get the Referer URL in CakePHP 3.X

Get Refer URL is not a big task in CakePHP now.

Just do the following to get Refer URL:

echo "Referrer URL=" . $this->referer('/') . "<BR>";

echo "Referrer URL=" . $this->referer('/', true) . "<BR>";

Which will output:

Referrer URL=http://localhost/cake/pages/database_check

Referrer URL=/pages/database_check