Revert "Revert "Instead using external API (api.qrserver.com) .. use chillerlan/php-qrcode""

This reverts commit 630bbf3aea.
This commit is contained in:
giandonato.inverso@edempg.it
2024-12-23 18:52:11 +01:00
parent 630bbf3aea
commit 531820e2a8
4 changed files with 303 additions and 31 deletions
+87 -10
View File
@@ -1,15 +1,82 @@
FROM php:latest
FROM php:8.3
RUN apt-get update && \
apt-get install -y --no-install-recommends less nano tini curl bash tar git zip unzip && \
#echo "**** # To install networking tools for testing purpose ****" && \
apt-get install -y --no-install-recommends iputils-ping dnsutils net-tools procps && \
#echo "**** cleanup ****" && \
apt-get autoremove -y && \
apt-get clean -y
RUN if [ "$(grep '^VERSION_ID=' /etc/os-release | cut -d '=' -f 2 | tr -d '"')" -eq "9" ]; then \
sed -i -e 's/deb.debian.org/archive.debian.org/g' \
-e 's/security.debian.org/archive.debian.org/g' \
-e '/stretch-updates/d' /etc/apt/sources.list; \
fi
RUN apt-get update
RUN apt-get install -y --no-install-recommends libzip-dev libjpeg62-turbo-dev libpng-dev libfreetype6-dev
# Download script to install PHP extensions and dependencies
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions
RUN DEBIAN_FRONTEND=noninteractive apt-get update -q \
&& DEBIAN_FRONTEND=noninteractive apt-get install -qq -y \
curl \
dnsutils \
git \
iputils-ping \
less \
libzip-dev \
libjpeg62-turbo-dev \
libpng-dev \
libfreetype6-dev \
nano \
net-tools \
procps \
tar \
tini \
zip unzip \
# iconv, mbstring and pdo_sqlite are omitted as they are already installed
&& PHP_EXTENSIONS=" \
amqp \
bcmath \
bz2 \
calendar \
event \
exif \
gd \
gettext \
intl \
ldap \
memcached \
mysqli \
opcache \
pdo_mysql \
pdo_pgsql \
pgsql \
redis \
soap \
sockets \
xsl \
zip \
" \
&& case "$PHP_VERSION" in \
5.6.*) PHP_EXTENSIONS="$PHP_EXTENSIONS mcrypt mysql";; \
7.0.*|7.1.*) PHP_EXTENSIONS="$PHP_EXTENSIONS mcrypt";; \
esac \
# Install Imagick from master on PHP >= 8.3, because imagick 3.7.0 broke on latest PHP releases and Imagick maintainers don't care to tag a newer release
&& if [ $(php -r 'echo PHP_VERSION_ID;') -lt 80300 ]; then \
PHP_EXTENSIONS="$PHP_EXTENSIONS imagick"; \
else PHP_EXTENSIONS="$PHP_EXTENSIONS https://api.github.com/repos/Imagick/imagick/tarball/28f27044e435a2b203e32675e942eb8de620ee58"; \
fi \
&& install-php-extensions $PHP_EXTENSIONS \
&& if command -v a2enmod; then a2enmod rewrite; fi
# Install Composer.
ENV PATH=$PATH:/root/composer/vendor/bin \
COMPOSER_ALLOW_SUPERUSER=1 \
COMPOSER_HOME=/root/composer
RUN cd /opt \
# Download installer and check for its integrity.
&& curl -sSL https://getcomposer.org/installer > composer-setup.php \
&& curl -sSL https://composer.github.io/installer.sha384sum > composer-setup.sha384sum \
&& sha384sum --check composer-setup.sha384sum \
# Install Composer 2.
&& php composer-setup.php --install-dir=/usr/local/bin --filename=composer --2 \
# Remove installer files.
&& rm /opt/composer-setup.php /opt/composer-setup.sha384sum
RUN docker-php-source extract
RUN docker-php-ext-install pdo_mysql zip exif pcntl gd
@@ -17,7 +84,17 @@ RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli
RUN docker-php-ext-install gettext && docker-php-ext-enable gettext
RUN docker-php-ext-install sockets && docker-php-ext-enable sockets
RUN mkdir -p /opt && chmod 777 /opt
WORKDIR /opt
RUN git clone https://github.com/chillerlan/php-qrcode.git \
&& chmod -R 777 ./php-qrcode
RUN cp ./php-qrcode/composer.json /var/www/html/composer.json
RUN mkdir -p /var/www/html/test && chmod 777 /var/www/html/test
RUN cp ./php-qrcode/examples/image.php /var/www/html/test/image.php
RUN cp -R ./php-qrcode/src /var/www/html/
WORKDIR /var/www/html
RUN composer update
COPY ./src ./
RUN chmod 755 *;
EXPOSE 80
+2
View File
@@ -45,6 +45,7 @@
<option value="800">800</option>
<option value="900">900</option>
<option value="1000">1000</option>
<option value="2000">2000</option>
</select>
</div>
</div>
@@ -75,6 +76,7 @@
<option value="jpeg">JPEG</option>
<option value="jpg">JPG</option>
<option value="svg">SVG</option>
<option value="svgbw">SVG (BW)</option>
<option value="eps">EPS</option>
</select>
</div>
+1 -1
View File
@@ -58,7 +58,7 @@
</td>
<td><?php echo htmlspecialchars($row['filename']); ?></td>
<td><?php echo htmlspecialchars($row['type']); ?></td>
<td><?php echo $row['content']; ?></td>
<td><?php echo htmlspecialchars_decode($row['content']); ?></td>
<td>
<?php echo '<img src="'.SAVED_QRCODE_FOLDER.htmlspecialchars($row['qrcode']).'" width="100" height="100">'; ?>
</td>
+209 -16
View File
@@ -1,5 +1,19 @@
<?php
require_once 'config/config.php';
use chillerlan\QRCode\Common\EccLevel;
use chillerlan\QRCode\QRCode as QRCodeEx;
use chillerlan\QRCode\QROptions;
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\Output\QRImagick;
use chillerlan\QRCode\Output\QRGdImagePNG;
use chillerlan\QRCode\Output\QRGdImageJPEG;
use chillerlan\QRCode\Output\QREps;
use chillerlan\QRCode\Output\QRMarkupSVG;
use chillerlan\QRCode\Output\QRCodeOutputException;
use chillerlan\QRCode\Output\QROutputInterface;
use chillerlan\Settings\SettingsContainerInterface;
require_once __DIR__.'/../../vendor/autoload.php';
class Qrcode {
private string $table;
@@ -53,7 +67,7 @@ class Qrcode {
$size = 100;
if (isset($input_data['size']))
$size = min(max((int)$input_data['size'], 100), 1000);
$size = min(max((int)$input_data['size'], 100), 2000);
//character # deleted
$foreground = substr($input_data['foreground'], 1);
@@ -79,25 +93,204 @@ class Qrcode {
public function addQrcode($input_data, $data_to_db, $data_to_qrcode) {
$options = $this->setOptions($input_data);
if(!file_exists(SAVED_QRCODE_DIRECTORY.$data_to_db['filename'].'.'.$data_to_db['format'])){
$url =
'https://api.qrserver.com/v1/create-qr-code/?data='.
$data_to_qrcode.
'&amp;&size='.$options['size'].'x'.$options['size'].
'&ecc='.$options['errorCorrectionLevel'].
'&margin=0&color='.$options['foreground'].
'&bgcolor='.$options['background'].
'&qzone=2'.
'&format='.$data_to_db['format'];
$outputInterface = QRGdImagePNG::class;
$imageFormat = strtolower($data_to_db['format']);
$fileExt = $imageFormat;
$forceBlackWhite = false;
$content = file_get_contents($url);
$filename = SAVED_QRCODE_DIRECTORY.$data_to_db['filename'].'.'.$data_to_db['format'];
switch ($imageFormat)
{
case 'png':
$outputInterface = QRGdImagePNG::class;
$imageFormat = 'png';
break;
case 'gif':
$outputInterface = QRImagick::class;
$imageFormat = 'gif';
break;
case 'jpg':
$outputInterface = QRImagick::class;
$imageFormat = 'jpg';
break;
case 'jpeg':
$outputInterface = QRImagick::class;
$imageFormat = 'jpeg';
break;
case 'svg':
# $outputInterface = QRImagick::class;
$outputInterface = QRMarkupSVG::class;
$imageFormat = 'svg';
break;
case 'svgbw':
$outputInterface = QRMarkupSVG::class;
$imageFormat = 'svg';
$fileExt = 'svg';
$forceBlackWhite = true;
$data_to_db['format'] = $fileExt;
$data_to_db['qrcode'] = str_replace('.svgbw', '.svg', $data_to_db['qrcode']);
break;
case 'eps':
$outputInterface = QREps::class;
$imageFormat = 'eps';
break;
}
try{
file_put_contents($filename, $content);
if(!file_exists(SAVED_QRCODE_DIRECTORY.$data_to_db['filename'].'.' . $fileExt)){
$eccLevel = constant(EccLevel::class.'::'.strtoupper($options['errorCorrectionLevel']));
$qroptions = new QROptions;
$qroptions->outputInterface = $outputInterface;
$qroptions->outputBase64 = false;
$qroptions->eccLevel = $eccLevel;
$qroptions->quietzoneSize = 2;
$moduleValues = [
// finder
QRMatrix::M_FINDER_DARK => $options['foreground'],
QRMatrix::M_FINDER_DOT => $options['foreground'],
QRMatrix::M_FINDER => $options['background'],
// alignment
QRMatrix::M_ALIGNMENT_DARK => $options['foreground'],
QRMatrix::M_ALIGNMENT => $options['background'],
// timing
QRMatrix::M_TIMING_DARK => $options['foreground'],
QRMatrix::M_TIMING => $options['background'],
// format
QRMatrix::M_FORMAT_DARK => $options['foreground'],
QRMatrix::M_FORMAT => $options['background'],
// version
QRMatrix::M_VERSION_DARK => $options['foreground'],
QRMatrix::M_VERSION => $options['background'],
// data
QRMatrix::M_DATA_DARK => $options['foreground'],
QRMatrix::M_DATA => $options['background'],
// darkmodule
QRMatrix::M_DARKMODULE => $options['foreground'],
// separator
QRMatrix::M_SEPARATOR => $options['background'],
// quietzone
QRMatrix::M_QUIETZONE => $options['background'],
];
if(in_array($data_to_db['format'], ['png', 'jpg', 'gif'], true))
{
$moduleValues = array_map(function($v)
{
if(preg_match('/[a-f\d]{6}/i', $v) === 1)
{
return array_map('hexdec', str_split($v, 2));
}
return null;
}, $moduleValues);
$qroptions->moduleValues = $moduleValues;
}
catch(Exception $e){
else
{
$moduleValues = array_map(function($v)
{
if(preg_match('/[a-f\d]{6}/i', $v) === 1)
{
return '#' . $v ;
}
return null;
}, $moduleValues);
$qroptions->moduleValues = $moduleValues;
}
if ($outputInterface === QRMarkupSVG::class)
{
$qroptions->version = 7;
// if set to false, the light modules won't be rendered
$qroptions->drawLightModules = true;
$qroptions->svgUseFillAttributes = false;
// draw the modules as circles isntead of squares
$qroptions->drawCircularModules = true;
$qroptions->circleRadius = 0.4;
// connect paths
$qroptions->connectPaths = true;
// keep modules of these types as square
$qroptions->keepAsSquare = [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
];
if($forceBlackWhite)
{
$qroptions->drawLightModules = false;
$qroptions->drawCircularModules = false;
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
$qroptions->svgDefs = '
<linearGradient id="rainbow" x1="1" y2="1">
<stop stop-color="#' . $options['foreground'] . '" offset="0"/>
<stop stop-color="#' . $options['foreground'] . '" offset="1"/>
</linearGradient>
<style><![CDATA[
.dark{fill: url(#rainbow);}
.light{fill: #eee;}
]]></style>';
}
else
{
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
$qroptions->svgDefs = '
<linearGradient id="rainbow" x1="1" y2="1">
<stop stop-color="#e2453c" offset="0"/>
<stop stop-color="#e07e39" offset="0.2"/>
<stop stop-color="#e5d667" offset="0.4"/>
<stop stop-color="#51b95b" offset="0.6"/>
<stop stop-color="#1e72b7" offset="0.8"/>
<stop stop-color="#6f5ba7" offset="1"/>
</linearGradient>
<style><![CDATA[
.dark{fill: url(#rainbow);}
.light{fill: #eee;}
]]></style>';
}
}
else
{
$qroptions->version = -1;
$qroptions->scale = 20;
$qroptions->quality = 83;
}
if ($outputInterface === QRImagick::class)
{
$qroptions->imagickFormat = $imageFormat;
$qroptions->returnResource = true;
$imagick = (new QRCodeEx($qroptions))->render(urldecode($data_to_qrcode));
$imagick->scaleImage($options['size'], $options['size'], true);
$content = $imagick->getImageBlob();
$imagick->destroy();
}
else
{
$content = (new QRCodeEx($qroptions))->render(urldecode($data_to_qrcode));
}
$filename = SAVED_QRCODE_DIRECTORY.$data_to_db['filename'].'.' . $fileExt;
try
{
file_put_contents($filename, $content);
if ($outputInterface !== QRImagick::class &&
$outputInterface !== QRMarkupSVG::class)
{
$imagick = new \Imagick(realpath($filename));
$imagick->resizeImage($options['size'], $options['size'], imagick::FILTER_LANCZOS, 1, false);
$imagick->writeImage($filename);
$imagick->destroy();
}
}
catch(Exception $e)
{
$this->failure($e->getMessage());
}