Instead using external API (api.qrserver.com) .. use chillerlan/php-qrcode
This commit is contained in:
+87
-10
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -107,4 +109,4 @@
|
||||
<?php } else { ?>
|
||||
<input type="hidden" name="id_owner" value="<?php echo $_SESSION["user_id"];?>"/>
|
||||
<?php } ?>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
@@ -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>
|
||||
|
||||
+212
-19
@@ -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,28 +93,207 @@ 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.
|
||||
'&&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'];
|
||||
|
||||
try{
|
||||
file_put_contents($filename, $content);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
// If you want you can customi<e qr code with logo
|
||||
//$this->addLogo($data_to_db['qrcode'], $options['optionlogo']);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user