#StackBounty: #php #unit-testing #phpunit #mockery Adding interface to mock with Mockery (hard dependency)

Bounty: 50

I need to mock CurrencyEnum by overload it, but it’s not the end becouse i need to add interface to this mock.
This doesn’t work:

Mockery::mock('overload:'.CurrencyEnum::class);

Error: (..) must be an instance of BaseCurrency, instance of CurrencyEnum given.
I looked at MockeryContainer::mock and I dont’t have idea how to do it.
In example I want to test TestingClass::first() method

class CurrencyEnum implements BaseCurrency
{
    /* methods */
}


class TestingClass
{
    public function first(string $currencySymbol)
    {
        $abc = 'some_string';

        return $this->second($abc, new CurrencyEnum($currencySymbol));
    }

    private function second(string $abc, BaseCurrency $currency)
    {
        /* code */
    }
}


Get this bounty!!!

#StackBounty: #php #wordpress #file-upload How to show uploaded php file as plain text instead of executing it in wordpress?

Bounty: 50

Edit a testme.php file in /tmp.

<?php
echo  "test";
?>

Edit a new post titled test and upload file /tmp/testme.php ,pubish it with url http://home.local/wp/?p=4785.
enter image description here

I want to see the content in testme,click it,pop up new window in wordpress.
enter image description here

Go on to click it.test shown in webpage.

My expect :
1.just click testme in test post for one time.
2.show the testme.php as plain text ,

<?php
echo  "test";
?>

instead of the result of executing testme.php.

test

I make a configuration according some material show php file as plain text in apache.

sudo vim /etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
    ServerName www.home.local
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
        <Directory /var/www/html>
            Options Indexes FollowSymLinks MultiViews
            AllowOverride All
            allow from all
            php_flag engine off
            AddType text/plain php
        </Directory>
</VirtualHost>

Reboot apache2(build in debian).

sudo systemctl restart apache2

To open the post http://home.local/wp/?p=4785,i got the following output in webpage:

<?php
/**
 * Front to the WordPress application. This file doesn't do anything, but loads
 * wp-blog-header.php which does and tells WordPress to load the theme.
 *
 * @package WordPress
 */

/**
 * Tells WordPress to load the WordPress theme and output it.
 *
 * @var bool
 */
define('WP_USE_THEMES', true);

/** Loads the WordPress Environment and Template */
require( dirname( __FILE__ ) . '/wp-blog-header.php' );


Get this bounty!!!

#StackBounty: #php #nginx #configuration #dns #ipv6 Php and Nginx server slow when combining IPv4 with IPv6

Bounty: 50

I’m setting up a new server with Ubuntu 18.04.1 Nginx 1.14.0 and PHP 7.2.7 This is the first server that I try to setup with both IPv4 and IPv6 enabled. Everything works fine until I tested a page with a lot of missing images. It seems to take forever for the server to realise they are missing and respond to the http request. Some missing files give a HTTP status of “502 bad gateway”. When I remove the line “listen [::]:443 ssl http2;” in the nginx server conf file the problem is gone. Is it a DNS problem that causes these delays and 502 errors and what should I change in the setup?

The php script should not be the problem, because my old server (that is only IPv4 enabled and has even less memory), with the exact same page, loads very quick. Also, I think it is DNS related, because when I remove that line “listen [::]:443 ssl http2;” in the nginx server conf file, the problem is gone. When I cranck up the settings in /etc/php/7.2/fpm/pool.d/www.conf, errors go away and loading time comes close to the old server (see further below) even though that server has less memory, PHP version 5.5.9-1 Ubuntu 14.04.5 LTS and Nginx 1.4.6.

When accessing the server through its IPv6 2a03:b0c0:0:1010::190:6001, there is a certificate mismatch notification. However the nginx server setup (see contents listed below) leads both IPv4 and IPv6 to the same certificate. Accessing the server through its IPv4 https://37.139.19.66 immediately shows https://test.vuyk.eu

The zone file records:

AAAA    test.vuyk.eu    directs to 2a03:b0c0:0:1010::190:6001 3600
A   test.vuyk.eu    directs to 37.139.19.66           3600

The hosts file might be a problem, however the problem persists if the hosts file is emptied all together. Here is the contents:

127.0.0.1 localhost
::1 localhost
2a03:b0c0:0:1010::190:6001 localhost
#vuykhost2.vuyk.eu is the hostname of the server
127.0.1.1 vuykhost2.vuyk.eu 
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

Below is the nginx server configuration, again, when I remove the line “listen [::]:443 ssl http2;” everything works fine:

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        ssl_certificate /etc/letsencrypt/live/test.vuyk.eu/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/test.vuyk.eu/privkey.pem;
        include snippets/ssl-params.conf;

        server_name test.vuyk.eu;
        root /var/www/vuyk.eu/webroot;
        index index.php index.html index.htm ;

        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        location ~ .php$ {
            include fastcgi.conf;
            fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        }
}

nginx.conf

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 2048;
    multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    #   keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # SSL Settings
    ##

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip             on;
    gzip_comp_level  2;
    gzip_min_length  1000;
    gzip_proxied     expired no-cache no-store private auth;
    gzip_types       text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
    client_body_buffer_size 10K;
    client_header_buffer_size 1k;
    client_max_body_size 100m;
    large_client_header_buffers 4 8k;
    fastcgi_buffers 16 16k;
    fastcgi_buffer_size 32k;
    fastcgi_read_timeout 500; #gateway probleem
    client_body_timeout 12;
    client_header_timeout 12;
    keepalive_timeout 25;
    send_timeout 10;
}

A part of the nginx error.log:

2018/08/30 16:25:27 [error] 29228#29228: *76 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 2a02:a440:91e3:1:4481:654b:a3e8:9617, server: test.vuyk.eu, request: "GET /images/klanten1/JHoogeveen.gif HTTP/2.0", upstream: "fastcgi://unix:/run/php/php7.2-fpm.sock:", host: "test.vuyk.eu", referrer: "https://test.vuyk.eu/portfolio-2"

Messages from the php7.2-fpm.log (there are a lot similar lines)

[30-Aug-2018 16:16:08] WARNING: [pool www] server reached pm.max_children setting (15), consider raising it
[30-Aug-2018 16:16:27] WARNING: [pool www] child 29026, script '/var/www/vuyk.eu/webroot/index.php' (request: "GET /index.php") execution timed out (22.937711 sec), terminating
[30-Aug-2018 16:16:27] WARNING: [pool www] child 29245 exited on signal 15 (SIGTERM) after 20.490546 seconds from start
[30-Aug-2018 16:16:27] NOTICE: [pool www] child 29263 started

Below is the timeline of HTTP requests and replies.

GET https://test.vuyk.eu/portfolio-2 [HTTP/2.0 200 OK 132ms]
GET https://test.vuyk.eu/templates/purity_iii/css/bootstrap.css [HTTP/2.0 200 OK 40ms]
GET https://test.vuyk.eu/templates/system/css/system.css [HTTP/2.0 200 OK 50ms]
GET https://test.vuyk.eu/templates/purity_iii/css/template.css [HTTP/2.0 200 OK 50ms]
GET https://test.vuyk.eu/templates/purity_iii/fonts/font-awesome/css/font-awesome.min.css [HTTP/2.0 200 OK 50ms]
GET https://test.vuyk.eu/templates/purity_iii/css/layouts/corporate.css [HTTP/2.0 200 OK 50ms]
GET https://test.vuyk.eu/media/jui/js/jquery.min.js?48b6d1b3850bca834b403c58682b4579 [HTTP/2.0 200 OK 60ms]
GET https://test.vuyk.eu/media/jui/js/jquery-noconflict.js?48b6d1b3850bca834b403c58682b4579 [HTTP/2.0 200 OK 60ms]
GET https://test.vuyk.eu/media/jui/js/jquery-migrate.min.js?48b6d1b3850bca834b403c58682b4579 [HTTP/2.0 200 OK 60ms]
GET https://test.vuyk.eu/media/system/js/caption.js?48b6d1b3850bca834b403c58682b4579 [HTTP/2.0 200 OK 70ms]
GET https://test.vuyk.eu/plugins/system/t3/base-bs3/bootstrap/js/bootstrap.js? 8b6d1b3850bca834b403c58682b4579 [HTTP/2.0 200 OK 80ms]
GET https://test.vuyk.eu/plugins/system/t3/base-bs3/js/jquery.tap.min.js [HTTP/2.0 200 OK 80ms]
GET https://test.vuyk.eu/plugins/system/t3/base-bs3/js/script.js [HTTP/2.0 200 OK 70ms]
GET https://test.vuyk.eu/plugins/system/t3/base-bs3/js/menu.js [HTTP/2.0 200 OK 70ms]
GET https://test.vuyk.eu/templates/purity_iii/js/script.js [HTTP/2.0 200 OK 70ms]
GET https://test.vuyk.eu/plugins/system/t3/base-bs3/js/nav-collapse.js [HTTP/2.0 200 OK 70ms]
GET https://test.vuyk.eu/templates/purity_iii/css/custom-vuyk.css [HTTP/2.0 200 OK 70ms]
GET https://test.vuyk.eu/images/klanten1/schipper2.gif [HTTP/2.0 502 Bad Gateway 23988ms]
GET https://test.vuyk.eu/images/klanten1/Kuiper.gif [HTTP/2.0 502 Bad Gateway 24038ms]
GET https://test.vuyk.eu/images/klanten1/WindMatch.gif [HTTP/2.0 502 Bad Gateway 24008ms]
GET https://test.vuyk.eu/images/klanten1/Tuinland.gif [HTTP/2.0 502 Bad Gateway 24018ms]
GET https://test.vuyk.eu/images/klanten1/Wezenberg.gif [HTTP/2.0 502 Bad Gateway 24038ms]
GET https://test.vuyk.eu/images/klanten1/Morgenster.gif [HTTP/2.0 502 Bad Gateway 23998ms]
GET https://test.vuyk.eu/images/klanten1/Harrie-boerhof.gif [HTTP/2.0 502 Bad Gateway 24028ms]
GET https://test.vuyk.eu/images/klanten1/Lococensus.gif [HTTP/2.0 502 Bad Gateway 23998ms]
GET https://test.vuyk.eu/images/klanten1/JHoogeveen.gif [HTTP/2.0 502 Bad Gateway 23978ms]
GET https://test.vuyk.eu/images/klanten1/DeDeur.gif [HTTP/2.0 502 Bad Gateway 23988ms]
GET https://test.vuyk.eu/images/klanten1/Runhaar.gif [HTTP/2.0 502 Bad Gateway 23958ms]
GET https://test.vuyk.eu/images/klanten1/Schunselaar-schildersbedrijf.gif [HTTP/2.0 502 Bad Gateway 23948ms]
GET https://test.vuyk.eu/images/klanten1/Capelle.gif [HTTP/2.0 502 Bad Gateway 23958ms]
GET https://test.vuyk.eu/images/klanten1/Distantlake.gif [HTTP/2.0 502 Bad Gateway 24038ms]
GET https://test.vuyk.eu/images/klanten1/Eikenaar.gif [HTTP/2.0 502 Bad Gateway 24018ms]
GET https://test.vuyk.eu/images/klanten1/FFWD.gif [HTTP/2.0 404 Not Found 26274ms]
GET https://test.vuyk.eu/images/klanten1/Veltec.gif [HTTP/2.0 404 Not Found 26791ms]
GET https://test.vuyk.eu/images/klanten1/Heutink.gif [HTTP/2.0 404 Not Found 26811ms]
GET https://test.vuyk.eu/images/klanten1/Lindeboom.gif [HTTP/2.0 404 Not Found 26777ms]
GET https://test.vuyk.eu/images/klanten1/aataxi.gif [HTTP/2.0 404 Not Found 26828ms]
GET https://test.vuyk.eu/images/klanten1/Aewind.gif [HTTP/2.0 404 Not Found 26811ms]
GET https://test.vuyk.eu/images/klanten1/Praatmaatgroep.gif [HTTP/2.0 404 Not Found 26800ms]
GET https://test.vuyk.eu/media/system/css/system.css [HTTP/2.0 200 OK 20ms]
JQMIGRATE: Migrate is installed, version 1.4.1 jquery-migrate.min.js:2:542
GET https://test.vuyk.eu/images/logo.gif [HTTP/2.0 200 OK 20ms]
GET https://test.vuyk.eu/images/reclame-en-communicatie.gif [HTTP/2.0 200 OK 20ms]
GET https://test.vuyk.eu/fonts/opensans-regular-webfont.woff [HTTP/2.0 200 OK 40ms]
GET https://test.vuyk.eu/templates/purity_iii/fonts/font-awesome/fonts/fontawesome-webfont.woff2?v=4.7.0 [HTTP/2.0 200 OK 70ms]

Edit: increased pm.max_children from 15 to 35. This solves the 502 problem and generates a new php warning:

[19-Sep-2018 11:28:05] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 0 idle, and 32 total children

Note: comparing with the same page on the old server, who has a pm.max_children setting of 5, there is still a long loading time, 8,4 seconds versus 3,16 seconds.
Below is the timeline of HTTP requests again:

200 GET portfolio-2 test.vuyk.eu document html 4,16 KB 10,84 KB → 267 ms
200 GET custom-vuyk.css test.vuyk.eu stylesheet css 4,09 KB 16,65 KB → 70 ms
404 GET schipper2.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 5901 ms
404 GET Kuiper.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7031 ms
404 GET WindMatch.gif test.vuyk.eu img html 3,26 KB 7,96 KB→ 5190 ms
404 GET Tuinland.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 6741 ms
404 GET Wezenberg.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 4910 ms
404 GET Morgenster.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 6571 ms
404 GET Harrie-boerhof.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 4820 ms
404 GET Lococensus.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 4980 ms
200 GET bootstrap.css test.vuyk.eu stylesheet css 26,13 KB 150,67 KB → 40 ms
200 GET system.css test.vuyk.eu stylesheet css 1,16 KB 894 B → 40 ms
200 GET template.css test.vuyk.eu stylesheet css 14,95 KB 70,55 KB → 40 ms
200 GET font-awesome.min.css test.vuyk.eu stylesheet css 7,90 KB 30,27 KB → 50 ms
200 GET corporate.css test.vuyk.eu stylesheet css 1,02 KB 752 B → 50 ms
200 GET jquery.min.js?48b6d1b3850bca834b403c58682b4579 test.vuyk.eu script js 37,40 KB 94,89 KB → 60 ms
200 GET jquery-noconflict.js?48b6d1b3850bca834b403c58682b4579 test.vuyk.eu script js 328 B 21 B → 70 ms
200 GET jquery-migrate.min.js?48b6d1b3850bca834b403c58682b4579 test.vuyk.eu script js 4,42 KB 9,82 KB → 70 ms
200 GET caption.js?48b6d1b3850bca834b403c58682b4579 test.vuyk.eu script js 800 B 491 B → 70 ms
200 GET bootstrap.js?48b6d1b3850bca834b403c58682b4579 test.vuyk.eu script js 17,01 KB 67,34 KB → 70 ms
200 GET jquery.tap.min.js test.vuyk.eu script js 1,17 KB 1,84 KB → 70 ms
200 GET script.js test.vuyk.eu script js 2,66 KB 6,26 KB → 70 ms
200 GET menu.js test.vuyk.eu script js 4,96 KB 16,48 KB → 70 ms
200 GET script.js test.vuyk.eu script js 1,50 KB 2,82 KB → 70 ms
200 GET nav-collapse.js test.vuyk.eu script js 1,81 KB 4,53 KB → 70 ms
404 GET JHoogeveen.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7141 ms
404 GET DeDeur.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 6401 ms
404 GET Runhaar.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 6861 ms
404 GET Schunselaar-schildersbedrijf.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7421 ms 
404 GET Capelle.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7171 ms
404 GET Distantlake.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7251 ms 
404 GET Eikenaar.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7191 ms
404 GET FFWD.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7141 ms 
404 GET Veltec.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7551 ms
404 GET Heutink.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7051 ms
404 GET Lindeboom.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7311 ms
404 GET aataxi.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7561 ms
404 GET Aewind.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7631 ms
404 GET Praatmaatgroep.gif test.vuyk.eu img html 3,26 KB 7,96 KB → 7591 ms
200 GET system.css test.vuyk.eu stylesheet css 845 B 1,41 KB → 10 ms
200 GET logo.gif test.vuyk.eu img gif 6,17 KB 5,88 KB → 20 ms
200 GET reclame-en-communicatie.gif test.vuyk.eu img gif 9,54 KB 9,25 KB → 20 ms
200 GET opensans-regular-webfont.woff test.vuyk.eu font font-woff 24,45 KB 24,15 KB → 40 ms
200 GET fontawesome-webfont.woff2?v=4.7.0 test.vuyk.eu font octet-stream 75,66 KB 75,35 KB → 60 ms
200 GET js?id=UA-41464374-1 www.googletagmanager.com script js 28,01 KB 76,92 KB → 50 ms
200 GET analytics.js www.google-analytics.com script js 16,29 KB 38,76 KB → 20 ms
200 GET collect?v=1&_v=j69&a=1138059620&t=pageview&_s=1&dl=https://test.vuyk.eu/portfolio-2&ul=nl&de=UTF-8&dt=Portfolio-2&sd=24-bit&sr=1600x1200&vp=1583x1125&je=0&fl=31.0 r0&_u=AACAAUAB~&jid=442053766&gjid=162768711&cid=1071791154.1525078778&tid=UA-41464374-1&_gid=1927096468.1537349155&_r=1&gtm=u9c&z=1503882568
www.google-analytics.com img gif 444 B 35 B

The timeline of HTTP request of the old server:

200 GET portfolio-2 vuyk.eu document html 4,22 KB 10,83 KB → 230 ms 
200 GET bootstrap.css vuyk.eu stylesheet css 26,18 KB 150,67 KB → 46 ms 
200 GET system.css vuyk.eu stylesheet css 759 B 894 B → 107 ms 
200 GET template.css vuyk.eu stylesheet css 15,01 KB 70,55 KB → 119 ms 
200 GET font-awesome.min.css vuyk.eu stylesheet css 7,95 KB 30,27 KB → 111 ms 
200 GET corporate.css vuyk.eu stylesheet css 592 B 752 B → 112 ms 
200 GET jquery.min.js?48b6d1b3850bca834b403c58682b4579 vuyk.eu script js 37,46 KB 94,89 KB → 138 ms 
200 GET jquery-noconflict.js?6d1b3850bca834b403c58682b4579 vuyk.eu script js 393 B 21 B → 51 ms 
200 GET jquery-migrate.min.js?48b6d1b3850bca834b403c58682b4579 vuyk.eu script js 4,48 KB 9,82 KB → 72 ms 
200 GET caption.js?48b6d1b3850bca834b403c58682b4579 vuyk.eu script js 688 B 491 B → 72 ms 
200 GET bootstrap.js?48b6d1b3850bca834b403c58682b4579 vuyk.eu script js 17,07 KB 67,34 KB → 93 ms 
200 GET jquery.tap.min.js vuyk.eu script js 1,23    1,84 KB → 86 ms 
200 GET script.js vuyk.eu script js 2,72 KB 6,26 KB → 150 ms
200 GET menu.js vuyk.eu script js 5,02 KB 16,48 KB → 141 ms 
200 GET script.js vuyk.eu script js 1,56 KB 2,82 KB → 142 ms 
200 GET nav-apse.js vuyk.eu script js 1,87 KB 4,53 KB → 144 ms 
200 GET custom-vuyk.css vuyk.eu stylesheet css 4,15 KB 16,65 KB → 146 ms 
404 GET schipper2.gif vuyk.eu img html 327 B 162 B → 157 ms 
404 GET Kuiper.gif  vuyk.eu img html 327 B 162 B → 158 ms 
404 GET WindMatch.gif vuyk.eu img html 327 B 162 B → 149 ms 
404 GET Tuinland.gif vuyk.eu img html 327 B 162 B → 151 ms 
404 GET Wezenberg.gif vuyk.eu img html 327 B 162 B → 152 ms 
404 GET Morgenster.gif vuyk.eu img html 327 B 162 B → 150 ms 
404 GET Harrie-boerhof.gif vuyk.eu img html 327 B 162 B → 152 ms 
404 GET Lococensus.gif vuyk.eu img html 327 B 162 B → 152 ms 
404 GET JHoogeveen.gif vuyk.eu img html 327 B 162 B → 151 ms 
404 GET DeDeur.gif vuyk.eu img html 327 B 162 B → 154 ms 
404 GET Runhaar.gif vuyk.eu img html 327 B 162 B → 154 ms 
404 GET Schunselaar-schildersbedrijf.gif vuyk.eu img html 327 B 162 B → 154 ms 
404 GET Capelle.gif vuyk.eu img html 327 B 162 B → 157 ms 
404  GET Eikenaar.gif vuyk.eu img html 327   162 B → 158 ms 
404 GET FFWD.gif vuyk.eu img html 327 B 162 B → 161 ms 
404 GET Veltec.gif vuyk.eu img html 327 B 162 B → 166 ms 
404 GET Heutink.gif vuyk.eu img html 327 B 162 B → 166 ms 
404 GET Lindeboom.gif vuyk.eu img html 327 B 162 B → 166 ms 
404 GET Distantlake.gif vuyk.eu img html 327 B 162 B → 158 ms 
404 GET ataxi.gif uyk.eu img html 327 B 162 B → 160 ms 
404 GET Aewind.gif vuyk.eu img html 327 B 162   → 161 ms 
404 GET Praatmaatgroep.gif vuyk.eu img html 327 B 162 B → 163 ms 
200 GET system.css vuyk.eu stylesheet css 903 B 1,41 KB → 12 ms 
200 GET logo.gif vuyk.eu img gif 6,20 KB 5,88 KB → 14 ms 
404 GET schipper2.gif vuyk.eu img html 327 B 162 B → 13 ms 
404 GET Kuiper.gif vuyk.eu img html 327 B 162 B → 15 ms 
404 GET WindMatch.gif vuyk.eu img html 327 B 162 B → 16 ms 
404 GET Tuinland.gif vuyk.eu img html 327 B 162 B → 18 ms 
404 GET Wezenberg.gif vuyk.eu img html 327 B 162 B → 20 ms 
404 GET Morgenster.gif vuyk.eu img html 327 B 162 B → 23 ms 
404 GET Harrie-boerhof.gif vuyk.eu img html 327 B 162 B → 25 ms 
404 GET Lococensus.gif vuyk.eu img html 327 B 162 B → 26 ms 
404 GET JHoogeveen.gif vuyk.eu img html 327 B 162 B → 29 ms 
404 GET DeDeur.gif vuyk.eu img html 327 B 162 B → 30 ms 
404 GET Runhaar.gif vuyk.eu img html 327 B 162 B → 33 ms 
404 GET Schunselaar-schildersbedrijf.gif vuyk.eu img html 327 B 162 B → 35 ms 
404 GET Capelle.gif vuyk.eu img html 327 B 162 B → 37 ms 
404 GET Distantlake.gif vuyk.eu img html 327 B 162 B → 38 ms 
404 GET Eikenaar.gif vuyk.eu img html 327 B 162 B → 40 ms 
404 GET FFWD.gif vuyk.eu img html 327 B 162 B → 42 ms 
404 GET Veltec.gif vuyk.eu img html 327 B 162 B → 45 ms 
404 GET Heutink.gif vuyk.eu img html 327 B 162 B → 46 ms 
404 GET Lindeboom.gif vuyk.eu img html 327 B 162 B → 49 ms 
404 GET aataxi.gif vuyk.eu img html 327 B 162 B →   160 ms 
404 GET Aewind.gif vuyk.eu img html 327 B 162 B → 10 ms 
404 GET Praatmaatgroep.gif vuyk.eu img html 327 B 162 B → 13 ms 
200 GET reclame-en-communicatie.gif vuyk.eu img gif 9,57 KB 9,25 KB → 18 ms 
200 GET opensans-regular-webfont.woff vuyk.eu font octet-stream 24,44   24,15 KB → 43 ms 
200 GET fontawesome-webfont.woff2?v=4.7.0 vuyk.eu font octet-stream 75,64 KB 75,35 KB → 53 ms 
200 GET js?id=UA-41464374-1 www.googletagmanager.com script js 28,01 KB 76,92 KB → 179 ms 
200 GET analytics.js www.google-analytics.com script js 16,29 KB 38,76 KB → 15 ms 
200 GET collect?v=1&_v=j69&a=1196607213&t=pageview&_s=1&dl=https://vuyk.eu/portfolio-2&ul=nl&de=UTF-8&dt=Portfolio-2&sd=24-bit&sr=1600x1200&vp=1583x1125&je=0&fl=31.0 r0&_u=AACAAUAB~&jid=593009893&gjid=1416231654&cid=1071791154.1525078778&tid=UA-41464374-1&_gid=1927096468.1537349155&_r=1&gtm=u9c&z=1966144014
www.google-analytics.com img gif 444 B 35 B

Edit: errors go away and loading time comes close to the old server when I cranck up the settings in /etc/php/7.2/fpm/pool.d/www.conf like so:

pm.max_children = 100
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 30

The old server settings:

pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

Any idea what causes these differences?


Get this bounty!!!

#StackBounty: #php #laravel-5 #geolocation How to group objects based on longitude/latitude proximity using laravel/php

Bounty: 100

I have a group of users. The user count could be 50 or could be 2000. Each should have a long/lat that I have retrieved from Google Geo api.

I need to query them all, and group them by proximity and a certain count. Say the count is 12 and I have 120 users in the group. I want to group people by how close they are (long/lat) to other people. So that I wind up with 10 groups of people who are close in proximity.

I currently have the google geo coding api setup and would prefer to use that.

TIA.

— Update
I have been googling about this for awhile and it appears that I am looking for a spatial query that returns groups by proximity.


Get this bounty!!!

#StackBounty: #java #php #xml #encryption #soap WSSE – XML SOAP security and key encryption and storing (EncryptedData/EncryptedKey)

Bounty: 300

I have now spent the last couple of days to find documentation about this..

I need to send a XML via SOAP with the WSSE security header, but don’t know how to encrypt and store the encrypted keys

Here is an example

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1">
            <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EK-1B758D26C51BFCD86614340101135741">
                <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
                <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                    <wsse:SecurityTokenReference>
                        <wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">MIIDODCCAiCgAwIBAgIGAU0FlCVCMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxCYW5rIENvbm5lY3QxFTATBgNVBAsTDEJhbmsgQ29ubmVjdDEdMBsGA1UEAxMUQmFuayBDb25uZWN0IElBLXRlc3QwHhcNMTUwNDI5MTQyODI0WhcNMTgwNDI5MTQyODI0WjAcMRowGAYDVQQDExFiYW5rIGNvbm5lY3QtdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI23KdtaRKPTFTe/A1PnsF9dpSlTiXurKmio0OCgTP9wClHwync3JsInRwGTooA20P9zWobUnEFbEiAgRVYCxuYoldRE6NLhSC854/YTjMBeevH1TNa38lpavGiI4UwFhg70U9/JuYs21hoFyzVfaWlVfOkAMm1U/n4wHq6FZW461S5PY4A/UI1Mr8WgeIHU9GqMBtFvjynzq3SLenOPgdmKtyJ3V8EOU+DlgwKmDbxMVMtYNDZtoQvOWnuvlJ6ICDcqcW7OUkmwCKodjxxPvrdaPxyZDhT7h4FgRtrAOS8qR6L7x9D4ZIoxOMPudGvr99OSb4KVtaAEt/R7hKxG3OsCAwEAAaNCMEAwHwYDVR0jBBgwFoAU680YSkZnx1IaJAmI49LlTGiia0wwHQYDVR0OBBYEFMaWOY7Vf/iB3WVA96j5kRtbF8prMA0GCSqGSIb3DQEBCwUAA4IBAQAJ+bssSFWE6KsYT7HSDKag4Eot7yNGMY4Don/MilDnOREdu20QUS131DKrSkpBQiCXbyRUQjUoun4yue0EG+rlG3QUIlNNdJ4KZJB+dTYdLUV7XTYJNPimKAmoZ+PFNvT1eGgWcMT+MbTfpk0mw0V8IprYGa8UPchd6vtSVwpbTcPc/F4bgUTlm/V+FG4bQS61gF0koj0DEZjzat7CBHpozRgfRlXgwu26vnhWGc99uKH4GAKN4JpqPi/6Yz+7iQNJUC3yeezgBxFrIXuLpkBZSP4zunf9VxsICnxkFUXOTuYBdcbhPNzqMknD5ijFcFRZITwdv7x3uJGLkM7iUfBp</wsse:KeyIdentifier>
                    </wsse:SecurityTokenReference>
                </ds:KeyInfo>
                <xenc:CipherData>
                    <xenc:CipherValue>af9+FhA91ytLwjeRvTYJsRCkhjHmAQGwqYwMBoNZBn7BZhF/a6EUpM9ByarVhx1SRCpjW5fb8tBVuJO1ZkjfTUZ5EAh/oDLbkmwPdSAAVzmAURHwCq3XQgMZV3lAczlLnPamxjjZBCGqxvAmBo1CvFFPC4AcBedqY92mP8XGyVHpS7JYKOxqXK2vUA1by7371x+Mu0aoS2zJPyPLa1IPwOYgR9qicmWz1RNPiEVA8ZBCN0NRyg7FLJxdUcE81z+1SjButBo2j3qcwkNcecHzZAnweY+LSWp3H5JA3WNzUHUuvFHEaPzT5jd7fUI16xo8NLK8/Rd8Eq/zDD+T3baeVQ==</xenc:CipherValue>
                </xenc:CipherData>
                <xenc:ReferenceList>
                    <xenc:DataReference URI="#ED-1B758D26C51BFCD86614340101135852"/>
                </xenc:ReferenceList>
            </xenc:EncryptedKey>
        </wsse:Security>
        <technicalAddress xmlns="http://example.com/schema/2014" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"/>
        <activationHeader xmlns="http://example.com/schema/2014" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#">
            <organisationIdentification>
                <mainRegistrationNumber>8079</mainRegistrationNumber>
                <isoCountryCode>DK</isoCountryCode>
            </organisationIdentification>
            <functionIdentification>112233445566778899</functionIdentification>
            <erpInformation/>
            <endToEndMessageId>d28b6a7dad414014a59029ef1a7e84d4</endToEndMessageId>
            <createDateTime>2015-06-11T10:08:33.258+02:00</createDateTime>
        </activationHeader>
    </soap:Header>
    <soap:Body>
        <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="ED-1B758D26C51BFCD86614340101135852" Type="http://www.w3.org/2001/04/xmlenc#Content">
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey">
                    <wsse:Reference URI="#EK-1B758D26C51BFCD86614340101135741"/>
                </wsse:SecurityTokenReference>
            </ds:KeyInfo>
            <xenc:CipherData>
                <xenc:CipherValue>dTSVuEJ90OYguQOsOz2ZtcE2mybwuvVl19pp7/e5yuvNygx3w5v+prpEvbjYLauiIAB3lrVDK2astJeYJGnDbaVJVeU0YqH5ItYVn7Wz36jJM52KB+UNbYo8EdTKYjsZuADzH+tAoA+pwYxGBXMEQctNI+C711HgP2hbpHNYOG7nAMOIrP/0B3FCy+st+9CbYlwAEENreTYunEEA41hciFnWCsIx0el7OeuiA6V51fAmvrF19RPNKwaptvbvmVdKj//RQ/0U1kRny16mDnFfX92bI3HBQm4XJA0nEfSvio7EUAAdhe77GMfu7+JELqXNowPGPLlvrbCFYnQhxGRITHtTIEbtJA6MKtBzHgjtw5pt7oWxKgGUnaJTfOPOSv43RLFGggkT/+gTjnZOagu8hhXp0x5HXJuZzw90aIS3jAfSPDc2ivct4WhWk0wcuQyC2rAh4I7gtiR+LqJJGqvucw4S+NR95FunKHKEW4yasKW1oU31/rRbp4Bmwo6BPsQlxnaSHPtk68IVkYDBslz1A5gOP+M/Iam2WI02y6sE/7aAH1ruN3pZlVuYFc3JDNHOPOvevP110d60lroknGdc9vxcFfj48OCKw/8Ed6tiXtAvk0Qu9Qt4ZyLUoPKIWEqjdLjwVadTDJQFAxRptNgiCos7s0czadUu7FNCRxfndjDxhA7trvys44ufEyK++YzZIgNu3r4dywNI22Nm+JZtLj+rX8ARE6FTPlxGBD0SSdXsfCfY2N1ytBBHQRnPsVaHK1p7KOhwQVbqEupcGyvaRolnymOzDLGFdS06OGYFrYXdgIbuqYtZP8QerXtUl0sWNAvvqHSPCQcpKecpMEecar+FUVwLEA+H1wzOprCMbRR+EgIboeDqQ7GxXqugkuFyvnlLDgxnaWhEhQb/5kAcQmnyUZ57MhDcUJqqQ4Cdmwrcxho1P+YqWY9yn0E86F+hl5976a/gH5KBobB84OWmgcX42eAmqpJf+8c8SuBv+7NctbQOk21aYlFEpkwSme/kG1/edtyoHQH/hF0RB1cT8g+u9S9AK2rs3s2G+Ap0U5oyY8pqJalGdZSBudE0sU4mhOV8trtx0FrN9A7pNkTcGPH25nCtyIz6rzR+DP8Mtgw5385s5ivVlDb+z74Wbh6iu7ZkVAogNTpUYU/1BxDXWJqFMkFmfziNxQ5AQqm1vGlBzXifoQkUFX1riutNphmu0Hs+7KMmMLvtW2cXmQDpkHFKVheeN4w7pBCEZ8KhZ0VTOwRZcdvrNcpYfXM13/QdTHQmCqqwgS/VvlUFz7PDn0/OKo6moUic8W6b1iEvd3kfc7QkunxoOUoJr4RwJ+PqCzN6PxQivAFA2tmDPc8qEa1PAdxTeNFoR/6dNQRojouuJq3C1LrbmGf6lQPvKi3KeKHXyjmDr7Tve+al2tcWJVr+1qEM3/XuthoiZbuTDxYUjZ2nf2fhHrmNcfvrfNxSNHVdQPp2R9Rf3eGxlRJsmRpef66VbYhOpmiH4xmq45EWiyBZmYm+tZtjsP51EDMIvdFbVRSGO/hMqURrDSsJXJeot27Iup2s0P2n/6a9k0c4SVvf/WXNN5x9JNvjU97bQNDQRfonJmo9pRYYHl1tSqNIYBK7KsMH+qr1vmiJuhrXUuL/RtOKvE9KXQ8kGoC9oF5rFn21z40ElxG5XRTASg==</xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </soap:Body>
</soap:Envelope>

First of all I have never worked with SOAP before so chances I do things wrong has pretty good odds 🙂

Have found something here, but I need more details https://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html#aes256-cbc

How are the iv and the key stored in CipherValue in the header?

When sending the XML request to the webservice I get this error

23-08-2018 12:50:02   General exception:Padding is invalid and cannot be removed.
23-08-2018 12:50:02   Stack trace:    at System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count)
   at System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.Xml.EncryptedXml.DecryptData(EncryptedData encryptedData, SymmetricAlgorithm symmetricAlgorithm)
   at SomeClassCore.XmlSecurity.Decryptor.DecryptData(Byte[] symmetricKey)
   at SomeClassCore.SecurityServiceImpl.UnwrapRequest(ServiceRequest serviceRequest)
   at BD.BCA.MessageHandler.MessageHandler.ProcessRequest(HttpContext context)

Have searched a bit more.. Maybe the iv must be a part of the stored data. But it’s still not working? Same error as above

class Encryption {
    public function data_encrypt(string $data, string $cipher, int $key_length): Array{
        $iv     = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
        $key    = openssl_random_pseudo_bytes($key_length);

        return [
            'data'  => base64_encode($iv.openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA, $iv)),
            'key'   => $key
        ];
    }

    public function key_encrypt(string $key): string{
        $public_cert = openssl_pkey_get_public('contents of public cert');
        openssl_public_encrypt($key, $data, $public_cert, OPENSSL_PKCS1_OAEP_PADDING);
        openssl_free_key($public_cert);

        return base64_encode($data);
    }
}

$Enc = new Encryption;
$data_encrypted = $Env->data_encrypt('The message I want to encrypt', 'AES-256-CBC', 32);

//  This base64 encoded string goes to <EncryptedData>
$data_encrypted['data'];

//  This base64 encoded string goes to <EncryptedKey> in the header
$Enc->key_encrypt($data_encrypted['key']);

update

Have been in contact with the maintainer of the webservice and OAEP padding is used with the RSA encryption and PKCS7 padding is used with AES chipher..

As I can see this is also what I do?


Get this bounty!!!

#StackBounty: #php #chess PHP Chess Version 2

Bounty: 50

For programming practice, I created a chess program in PHP (my most comfortable language).

The program reads a FEN (a string with the location of all the pieces on the board) from the URL, generates a board, then generates all the legal moves for that position. Then when you click the move, it loads the same file but with a new ?fen= in the URL.

The legal moves list code is 100% complete. It handles all special cases, including pawn promotion, en passant, castling, not allowing moves that place/keep your own king in check, etc.

Moves can be made by double clicking on the move, hitting “Make A Move”, or drag and dropping a piece on the board.

I am hoping for feedback/advice to help me make the following improvements to the PHP code:

  • Make the code more readable / more organized / use classes better.
  • Speed up the code. Complex positions with lots of moves are taking 1500ms to render. This speed is acceptable for a browser based game, but would be way too slow if I wanted to turn this code into a chess engine (chess A.I.)
  • Find and eliminate bugs.
  • Teach me good programming practices. (I am an amateur programmer who has taken 1 computer science class in my life)

Any feedback that improves the code would be appreciated. Thank you.

Humble beginnings: Version 1 of the program can be found here.

Website

http://www.clania.net/admiraladama/chess_v2

Screenshot

Screenshot

index.php

<?php

$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$start = $time;

error_reporting(-1);
ini_set('display_errors', 'On');

require_once('ChessGame.php');
require_once('ChessBoard.php');
require_once('ChessPiece.php');
require_once('ChessMove.php');
require_once('ChessSquare.php');
require_once('Dictionary.php');

$game = new ChessGame();

if ( isset($_GET['reset']) ) {
    // Skip this conditional. ChessGame's FEN is the default, new game FEN and doesn't need to be set again.
} elseif ( isset($_GET['move']) ) {
    $game->board->set_fen($_GET['move']);
} elseif ( isset($_GET['fen']) ) {
    $game->board->set_fen($_GET['fen']);
}

$fen = $game->board->get_fen();
$side_to_move = $game->board->get_side_to_move_string();
$who_is_winning = $game->board->get_who_is_winning_string();
$graphical_board_array = $game->board->get_graphical_board();
$legal_moves = $game->get_legal_moves_list($game->board->color_to_move, $game->board);

require_once('view.php');

ChessGame.php

<?php

class ChessGame {
    var $board;

    function __construct($fen = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1') {
        $this->board = new ChessBoard($fen);
    }

    function __clone() {
        $this->board = clone $this->board;

        if ( $this->move_list ) {
            $array = array();
            foreach ( $this->move_list as $key => $move ) {
                array_push($array, clone $move);
            }
            $this->move_list = $array;
        }
    }

    function get_legal_moves_list(
        $color_to_move,
        $board,
        $eliminate_king_in_check_moves = TRUE
    ) {
        $pieces_to_check = $this->get_all_pieces_by_color($color_to_move, $board);

        $moves = array();

        // Is player to move checkmated?
        // Is enemy checkmated?
        // If so, return NULL since there are no legal moves. The game is over!
        // Else you will get a weird list of legal moves including moves capturing the enemy king.

        foreach ( $pieces_to_check as $key => $piece ) {
            if ( $piece->type == 'pawn' ) {
                if ( $piece->color == 'white' ) {
                    $directions_list = array('north');
                    if ( $piece->on_rank(2) ) {
                        $moves = $this->add_slide_moves_to_moves_list($directions_list, 2, $moves, $piece, $color_to_move, $board);
                    } else {
                        $moves = $this->add_slide_moves_to_moves_list($directions_list, 1, $moves, $piece, $color_to_move, $board);
                    }

                    $directions_list = array('northeast', 'northwest');
                    $moves = $this->add_capture_moves_to_moves_list($directions_list, $moves, $piece, $color_to_move, $board);

                    // en passant
                    $moves = $this->add_en_passant_moves_to_moves_list($piece, $board, $moves);
                } elseif ( $piece->color == 'black' ) {
                    $directions_list = array('south');
                    if ( $piece->on_rank(7) ) {
                        $moves = $this->add_slide_moves_to_moves_list($directions_list, 2, $moves, $piece, $color_to_move, $board);
                    } else {
                        $moves = $this->add_slide_moves_to_moves_list($directions_list, 1, $moves, $piece, $color_to_move, $board);
                    }

                    $directions_list = array('southeast', 'southwest');
                    $moves = $this->add_capture_moves_to_moves_list($directions_list, $moves, $piece, $color_to_move, $board);

                    // en passant
                    $moves = $this->add_en_passant_moves_to_moves_list($piece, $board, $moves);
                }
            } elseif ( $piece->type == 'knight' ) {
                $oclock_list = array(1, 2, 4, 5, 7, 8, 10, 11);

                $moves = $this->add_jump_and_jumpcapture_moves_to_moves_list($oclock_list, $moves, $piece, $color_to_move, $board);
            } elseif ( $piece->type == 'bishop' ) {
                $directions_list = array(
                    'northwest',
                    'northeast',
                    'southwest',
                    'southeast'
                );

                $moves = $this->add_slide_and_slidecapture_moves_to_moves_list($directions_list, 7, $moves, $piece, $color_to_move, $board);
            } elseif ( $piece->type == 'rook' ) {
                $directions_list = array(
                    'north',
                    'south',
                    'east',
                    'west'
                );

                $moves = $this->add_slide_and_slidecapture_moves_to_moves_list($directions_list, 7, $moves, $piece, $color_to_move, $board);
            } elseif ( $piece->type == 'queen' ) {
                $directions_list = array(
                    'north',
                    'south',
                    'east',
                    'west',
                    'northwest',
                    'northeast',
                    'southwest',
                    'southeast'
                );

                $moves = $this->add_slide_and_slidecapture_moves_to_moves_list($directions_list, 7, $moves, $piece, $color_to_move, $board);
            } elseif ( $piece->type == 'king' ) {
                $directions_list = array(
                    'north',
                    'south',
                    'east',
                    'west',
                    'northwest',
                    'northeast',
                    'southwest',
                    'southeast'
                );
                $moves = $this->add_slide_and_slidecapture_moves_to_moves_list($directions_list, 1, $moves, $piece, $color_to_move, $board);

                // Set $king here so castling function can use it later.
                $king = $piece;
            }
        }

        if ( $moves === array() ) {
            $moves = NULL;
        }

        if ( $eliminate_king_in_check_moves ) {
            $enemy_color = $this->invert_color($color_to_move);

            // Eliminate king in check moves
            $new_moves = array();
            if ( ! $king ) {
                throw new Exception('ChessGame Class - Invalid FEN - One of the kings is missing');
            }
            foreach ( $moves as $key => $move ) {
                $friendly_king_square = $move->board->get_king_square($color_to_move);

                $squares_attacked_by_enemy = $this->get_squares_attacked_by_this_color($enemy_color, $move->board);

                if ( ! in_array($friendly_king_square->alphanumeric, $squares_attacked_by_enemy) ) {
                    array_push($new_moves, $move);
                }
            }

            $moves = $new_moves;

            // Move notation - disambiguate vague starting squares
            // foreach $moves as $key => $move
                // if $move->piece->type == queen, rook, knight, bishop
                    // make list of destination squares
                    // identify duplicates
                    // foreach duplicates as $key => $move2
                        // if column disambiguate this piece
                            // $move->set_disambiguation(column);
                        // elseif row disambiguates this piece
                            // $move->set_disambiguation(row);
                        // else
                            // $move->set_disambiguation(columnrow);

            // Castling
            // (castling does its own "king in check" checks so we can put this code after the "king in check" code)
            $squares_attacked_by_enemy = $this->get_squares_attacked_by_this_color($enemy_color, $board);
            $moves = $this->add_castling_moves_to_moves_list($moves, $king, $squares_attacked_by_enemy, $board);

            // if move puts enemy king in check, tell the $move object so it can add a + to the notation
            foreach ( $moves as $key => $move ) {
                $enemy_king_square = $move->board->get_king_square($enemy_color);

                $squares_attacked_by_moving_side = $this->get_squares_attacked_by_this_color($color_to_move, $move->board);

                if ( in_array($enemy_king_square->alphanumeric, $squares_attacked_by_moving_side) ) {
                    $move->set_enemy_king_in_check(TRUE);
                }
            }

            // alphabetize
        }

        return $moves;
    }

    function add_slide_and_slidecapture_moves_to_moves_list($directions_list, $spaces, $moves, $piece, $color_to_move, $board) {
        foreach ( $directions_list as $key => $direction ) {
            // $spaces should be 1 for king, 1 or 2 for pawns, 7 for all other sliding pieces
            // 7 is the max # of squares you can slide on a chessboard

            $xy = array(
                'north' => array(0,1),
                'south' => array(0,-1),
                'east' => array(1,0),
                'west' => array(-1,0),
                'northeast' => array(1,1),
                'northwest' => array(-1,1),
                'southeast' => array(1,-1),
                'southwest' => array(-1,-1)
            );

            // XY coordinates and rank/file are different. Need to convert.
            $xy = $this->convert_from_xy_to_rankfile($xy);

            $legal_move_list = array();

            for ( $i = 1; $i <= $spaces; $i++ ) {
                $current_xy = $xy[$direction];
                $current_xy[0] *= $i;
                $current_xy[1] *= $i;

                $ending_square = $this->square_exists_and_not_occupied_by_friendly_piece(
                    $piece->square,
                    $current_xy[0],
                    $current_xy[1],
                    $color_to_move,
                    $board
                );

                if ( $ending_square ) {
                    $capture = FALSE;

                    if ( is_a($board->board[$ending_square->rank][$ending_square->file], 'ChessPiece') ) {
                        if ( $board->board[$ending_square->rank][$ending_square->file]->color != $color_to_move ) {
                            $capture = TRUE;
                        }
                    }

                    array_push($legal_move_list, new ChessMove(
                        $piece->square,
                        $ending_square,
                        $piece->color,
                        $piece->type,
                        $capture,
                        $board
                    ));

                    if ( $capture ) {
                        // stop sliding
                        break;
                    } else {
                        // empty square
                        // continue sliding
                        continue;
                    }
                } else {
                    // square does not exist, or square occupied by friendly piece
                    // stop sliding
                    break;
                }
            }

            if ( $legal_move_list === array() ) {
                $legal_move_list = NULL;
            }

            if ( $legal_move_list ) {
                foreach ( $legal_move_list as $key2 => $value2 ) {
                    array_push($moves, $value2);
                }
            }
        }

        return $moves;
    }

    function add_capture_moves_to_moves_list($directions_list, $moves, $piece, $color_to_move, $board) {
        foreach ( $directions_list as $key => $direction ) {
            $xy = array(
                'north' => array(0,1),
                'south' => array(0,-1),
                'east' => array(1,0),
                'west' => array(-1,0),
                'northeast' => array(1,1),
                'northwest' => array(-1,1),
                'southeast' => array(1,-1),
                'southwest' => array(-1,-1)
            );

            // XY coordinates and rank/file are different. Need to convert.
            $xy = $this->convert_from_xy_to_rankfile($xy);

            $legal_move_list = array();

            $current_xy = $xy[$direction];

            $ending_square = $this->square_exists_and_not_occupied_by_friendly_piece(
                $piece->square,
                $current_xy[0],
                $current_xy[1],
                $color_to_move,
                $board
            );

            if ( $ending_square ) {
                $capture = FALSE;

                if ( is_a($board->board[$ending_square->rank][$ending_square->file], 'ChessPiece') ) {
                    if ( $board->board[$ending_square->rank][$ending_square->file]->color != $color_to_move ) {
                        $capture = TRUE;
                    }
                }

                if ( $capture ) {
                    $move = new ChessMove(
                        $piece->square,
                        $ending_square,
                        $piece->color,
                        $piece->type,
                        $capture,
                        $board
                    );

                    // pawn promotion
                    $white_pawn_capturing_on_rank_8 = $piece->type == "pawn" && $ending_square->rank == 8 && $piece->color == "white";
                    $black_pawn_capturing_on_rank_1 = $piece->type == "pawn" && $ending_square->rank == 1 && $piece->color == "black";
                    if (
                        $white_pawn_capturing_on_rank_8 || $black_pawn_capturing_on_rank_1
                    ) {
                        $promotion_pieces = array(
                            'queen',
                            'rook',
                            'bishop',
                            'knight'
                        );

                        foreach ( $promotion_pieces as $key => $type ) {
                            $move2 = clone $move;
                            $move2->set_promotion_piece($type);
                            array_push($legal_move_list, $move2);
                        }
                    } else {
                        array_push($legal_move_list, $move);
                    }
                }
            }

            if ( $legal_move_list === array() ) {
                $legal_move_list = NULL;
            }

            if ( $legal_move_list ) {
                foreach ( $legal_move_list as $key2 => $value2 ) {
                    array_push($moves, $value2);
                }
            }
        }

        return $moves;
    }

    function add_slide_moves_to_moves_list($directions_list, $spaces, $moves, $piece, $color_to_move, $board) {
        foreach ( $directions_list as $key => $direction ) {
            // $spaces should be 1 for king, 1 or 2 for pawns, 7 for all other sliding pieces
            // 7 is the max # of squares you can slide on a chessboard

            $xy = array(
                'north' => array(0,1),
                'south' => array(0,-1),
                'east' => array(1,0),
                'west' => array(-1,0),
                'northeast' => array(1,1),
                'northwest' => array(-1,1),
                'southeast' => array(1,-1),
                'southwest' => array(-1,-1)
            );

            // XY coordinates and rank/file are different. Need to convert.
            $xy = $this->convert_from_xy_to_rankfile($xy);

            $legal_move_list = array();

            for ( $i = 1; $i <= $spaces; $i++ ) {
                $current_xy = $xy[$direction];
                $current_xy[0] *= $i;
                $current_xy[1] *= $i;

                $ending_square = $this->square_exists_and_not_occupied_by_friendly_piece(
                    $piece->square,
                    $current_xy[0],
                    $current_xy[1],
                    $color_to_move,
                    $board
                );

                if ( $ending_square ) {
                    $capture = FALSE;

                    if ( is_a($board->board[$ending_square->rank][$ending_square->file], 'ChessPiece') ) {
                        if ( $board->board[$ending_square->rank][$ending_square->file]->color != $color_to_move ) {
                            $capture = TRUE;
                        }
                    }

                    if ( $capture ) {
                        // enemy piece in square
                        // stop sliding
                        break;
                    } else {
                        $new_move = new ChessMove(
                            $piece->square,
                            $ending_square,
                            $piece->color,
                            $piece->type,
                            $capture,
                            $board
                        );

                        // en passant target square
                        if (
                            $piece->type == 'pawn' &&
                            $i == 2
                        ) {
                            $en_passant_xy = $xy[$direction];
                            $en_passant_xy[0] *= 1;
                            $en_passant_xy[1] *= 1;

                            $en_passant_target_square = $this->square_exists_and_not_occupied_by_friendly_piece(
                                $piece->square,
                                $en_passant_xy[0],
                                $en_passant_xy[1],
                                $color_to_move,
                                $board
                            );

                            $new_move->board->set_en_passant_target_square($en_passant_target_square);
                        }

                        // pawn promotion
                        $white_pawn_moving_to_rank_8 = $piece->type == "pawn" && $ending_square->rank == 8 && $piece->color == "white";
                        $black_pawn_moving_to_rank_1 = $piece->type == "pawn" && $ending_square->rank == 1 && $piece->color == "black";
                        if (
                            $white_pawn_moving_to_rank_8 || $black_pawn_moving_to_rank_1
                        ) {
                            $promotion_pieces = array(
                                'queen',
                                'rook',
                                'bishop',
                                'knight'
                            );

                            foreach ( $promotion_pieces as $key => $type ) {
                                $move2 = clone $new_move;
                                $move2->set_promotion_piece($type);
                                array_push($legal_move_list, $move2);
                            }
                        } else {
                            array_push($legal_move_list, $new_move);
                        }

                        // empty square
                        // continue sliding
                        continue;
                    }
                } else {
                    // square does not exist, or square occupied by friendly piece
                    // stop sliding
                    break;
                }
            }

            if ( $legal_move_list === array() ) {
                $legal_move_list = NULL;
            }

            if ( $legal_move_list ) {
                foreach ( $legal_move_list as $key2 => $value2 ) {
                    array_push($moves, $value2);
                }
            }
        }

        return $moves;
    }

    function add_jump_and_jumpcapture_moves_to_moves_list($oclock_list, $moves, $piece, $color_to_move, $board) {
        foreach ( $oclock_list as $key => $oclock ) {
            $xy = array(
                1 => array(1,2),
                2 => array(2,1),
                4 => array(2,-1),
                5 => array(1,-2),
                7 => array(-1,-2),
                8 => array(-2,-1),
                10 => array(-2,1),
                11 => array(-1,2)
            );

            // XY coordinates and rank/file are different. Need to convert.
            $xy = $this->convert_from_xy_to_rankfile($xy);

            $ending_square = $this->square_exists_and_not_occupied_by_friendly_piece(
                $piece->square,
                $xy[$oclock][0],
                $xy[$oclock][1],
                $color_to_move,
                $board
            );

            $legal_move_list = array();

            if ( $ending_square ) {
                $capture = FALSE;

                if ( is_a($board->board[$ending_square->rank][$ending_square->file], 'ChessPiece') ) {
                    // enemy piece
                    if ( $board->board[$ending_square->rank][$ending_square->file]->color != $color_to_move ) {
                        $capture = TRUE;
                    }
                }

                array_push($legal_move_list, new ChessMove(
                    $piece->square,
                    $ending_square,
                    $piece->color,
                    $piece->type,
                    $capture,
                    $board
                ));
            }

            if ( $legal_move_list === array() ) {
                $legal_move_list = NULL;
            }

            if ( $legal_move_list ) {
                foreach ( $legal_move_list as $key2 => $value2 ) {
                    array_push($moves, $value2);
                }
            }
        }

        return $moves;
    }

    function add_castling_moves_to_moves_list($moves, $piece, $squares_attacked_by_enemy, $board) {
        $scenarios = array (
            array(
                'boolean_to_check' => 'white_can_castle_kingside',
                'color_to_move' => 'white',
                'rook_start_square' => new ChessSquare('h1'),
                'king_end_square' => new ChessSquare('g1'),
                'cannot_be_attacked' => array(
                    new ChessSquare('e1'),
                    new ChessSquare('f1'),
                    new ChessSquare('g1')
                ),
                'cannot_be_occupied' => array(
                    new ChessSquare('f1'),
                    new ChessSquare('g1')
                )
            ),
            array(
                'boolean_to_check' => 'white_can_castle_queenside',
                'color_to_move' => 'white',
                'rook_start_square' => new ChessSquare('a1'),
                'king_end_square' => new ChessSquare('c1'),
                'cannot_be_attacked' => array(
                    new ChessSquare('e1'),
                    new ChessSquare('d1'),
                    new ChessSquare('c1')
                ),
                'cannot_be_occupied' => array(
                    new ChessSquare('d1'),
                    new ChessSquare('c1'),
                    new ChessSquare('b1')
                )
            ),
            array(
                'boolean_to_check' => 'black_can_castle_kingside',
                'color_to_move' => 'black',
                'rook_start_square' => new ChessSquare('h8'),
                'king_end_square' => new ChessSquare('g8'),
                'cannot_be_attacked' => array(
                    new ChessSquare('e8'),
                    new ChessSquare('f8'),
                    new ChessSquare('g8')
                ),
                'cannot_be_occupied' => array(
                    new ChessSquare('f8'),
                    new ChessSquare('g8')
                )
            ),
            array(
                'boolean_to_check' => 'black_can_castle_queenside',
                'color_to_move' => 'black',
                'rook_start_square' => new ChessSquare('a8'),
                'king_end_square' => new ChessSquare('c8'),
                'cannot_be_attacked' => array(
                    new ChessSquare('e8'),
                    new ChessSquare('d8'),
                    new ChessSquare('c8')
                ),
                'cannot_be_occupied' => array(
                    new ChessSquare('d8'),
                    new ChessSquare('c8'),
                    new ChessSquare('b8')
                )
            ),
        );

        $legal_move_list = array();

        foreach ( $scenarios as $key => $value ) {
            // only check castling for current color_to_move
            if ( $value['color_to_move'] != $board->color_to_move ) {
                continue;
            }

            // make sure the FEN has castling permissions
            $boolean_to_check = $value['boolean_to_check'];
            if ( ! $board->castling[$boolean_to_check] ) {
                continue;
            }

            // check all cannot_be_attacked squares
            foreach ( $value['cannot_be_attacked'] as $key2 => $square_to_check ) {
                if ( in_array($square_to_check->alphanumeric, $squares_attacked_by_enemy) ) {
                    continue 2;
                }
            }

            // check all cannot_be_occupied_squares
            foreach ( $value['cannot_be_occupied'] as $key2 => $square_to_check ) {
                if ( $board->square_is_occupied($square_to_check) ) {
                    continue 2;
                }
            }

            // Make sure the rook is still there. This case should only occur in damaged FENs. If the rook isn't there, throw an invalid FEN exception (to prevent a clone error later on).
            $rook_start_square = $value['rook_start_square'];
            $rank = $rook_start_square->rank;
            $file = $rook_start_square->file;
            $piece_to_check = $board->board[$rank][$file];
            if ( ! $piece_to_check ) {
                throw new Exception('ChessGame Class - Invalid FEN - Castling permissions set to TRUE but rook is missing');
            }
            if (
                $piece_to_check->type != 'rook' ||
                $piece_to_check->color != $board->color_to_move
            ) {
                throw new Exception('ChessGame Class - Invalid FEN - Castling permissions set to TRUE but rook is missing');
            }

            // The ChessMove class handles displaying castling notation, taking castling privileges out of the FEN, and moving the rook into the right place on the board. No need to do anything extra here.
            array_push($legal_move_list, new ChessMove(
                $piece->square,
                $value['king_end_square'],
                $piece->color,
                $piece->type,
                FALSE,
                $board
            ));
        }

        if ( $legal_move_list === array() ) {
            $legal_move_list = NULL;
        }

        if ( $legal_move_list ) {
            foreach ( $legal_move_list as $key2 => $value2 ) {
                array_push($moves, $value2);
            }
        }

        return $moves;
    }

    function add_en_passant_moves_to_moves_list($piece, $board, $moves) {
        if ( $piece->color == 'white' ) {
            $capture_directions_from_starting_square = array('northeast', 'northwest');
            $enemy_pawn_direction_from_ending_square = array('south');
            $en_passant_rank = 5;
        } elseif ( $piece->color == 'black' ) {
            $capture_directions_from_starting_square = array('southeast', 'southwest');
            $enemy_pawn_direction_from_ending_square = array('north');
            $en_passant_rank = 4;
        }

        if ( $piece->on_rank($en_passant_rank) && $board->en_passant_target_square ) {
            $squares_to_check = $this->get_squares_in_these_directions($piece->square, $capture_directions_from_starting_square, 1);
            foreach ( $squares_to_check as $key => $square ) {
                if ( $square->alphanumeric == $board->en_passant_target_square->alphanumeric ) {
                    $move = new ChessMove(
                        $piece->square,
                        $square,
                        $piece->color,
                        $piece->type,
                        TRUE,
                        $board
                    );
                    $move->set_en_passant(TRUE);
                    $enemy_pawn_square = $this->get_squares_in_these_directions($square, $enemy_pawn_direction_from_ending_square, 1);
                    $move->board->remove_piece_from_square($enemy_pawn_square[0]);
                    array_push($moves, $move);
                }
            }
        }

        return $moves;
    }

    function convert_from_xy_to_rankfile($xy) {
        // XY coordinates and rank/file are different. Need to convert.
        // We basically need to flip X and Y to fix it.

        foreach ( $xy as $key => $value ) {
            $xy[$key] = array($value[1], $value[0]);
        }

        return $xy;
    }

    function get_all_pieces_by_color($color_to_move, $board) {
        $list_of_pieces = array();

        for ( $i = 1; $i <= 8; $i++ ) {
            for ( $j = 1; $j <=8; $j++ ) {
                $piece = $board->board[$i][$j];

                if ( $piece ) {
                    if ( $piece->color == $color_to_move ) {
                        array_push($list_of_pieces, $piece);
                    }
                }
            }
        }

        if ( $list_of_pieces === array() ) {
            $list_of_pieces = NULL;
        }

        return $list_of_pieces;
    }

    // positive X = east, negative X = west, positive Y = north, negative Y = south
    function square_exists_and_not_occupied_by_friendly_piece($starting_square, $x_delta, $y_delta, $color_to_move, $board) {
        $rank = $starting_square->rank + $x_delta;
        $file = $starting_square->file + $y_delta;

        $ending_square = $this->try_to_make_square_using_rank_and_file_num($rank, $file);

        // Ending square is off the board
        if ( ! $ending_square ) {
            return FALSE;
        }

        // Ending square contains a friendly piece
        if ( is_a($board->board[$rank][$file], 'ChessPiece') ) {
            if ( $board->board[$rank][$file]->color == $color_to_move ) {
                return FALSE;
            }
        }

        return $ending_square;
    }

    function try_to_make_square_using_rank_and_file_num($rank, $file) {
        $file_letters = new Dictionary(array(
            1 => 'a',
            2 => 'b',
            3 => 'c',
            4 => 'd',
            5 => 'e',
            6 => 'f',
            7 => 'g',
            8 => 'h'
        ));

        $alphanumeric = $file_letters->check_dictionary($file) . $rank;

        $valid_squares = array(
            'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8',
            'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8',
            'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8',
            'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8',
            'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8',
            'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8',
            'g1', 'g2', 'g3', 'g4', 'g5', 'g6', 'g7', 'g8',
            'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8'
        );


        if ( in_array($alphanumeric, $valid_squares) ) {
            return new ChessSquare($alphanumeric);
        } else {
            return FALSE;
        }
    }

    function invert_color($color) {
        if ( $color == 'white' ) {
            return 'black';
        } else {
            return 'white';
        }
    }

    function get_squares_attacked_by_this_color($color, $board) {
        $legal_moves_for_opponent = $this->get_legal_moves_list($color, $board, FALSE);

        $squares_attacked = array();
        foreach ( $legal_moves_for_opponent as $key => $move ) {
            // avoid duplicates
            if ( ! in_array($move->ending_square->alphanumeric, $squares_attacked) ) {
                array_push($squares_attacked, $move->ending_square->alphanumeric);
            }
        }

        return $squares_attacked;
    }

    // Used to generate en passant squares.
    function get_squares_in_these_directions($starting_square, $directions_list, $spaces) {
        $list_of_squares = array();

        foreach ( $directions_list as $key => $direction ) {
            // $spaces should be 1 for king, 1 or 2 for pawns, 7 for all other sliding pieces
            // 7 is the max # of squares you can slide on a chessboard

            $xy = array(
                'north' => array(0,1),
                'south' => array(0,-1),
                'east' => array(1,0),
                'west' => array(-1,0),
                'northeast' => array(1,1),
                'northwest' => array(-1,1),
                'southeast' => array(1,-1),
                'southwest' => array(-1,-1)
            );

            // XY coordinates and rank/file are different. Need to convert.
            $xy = $this->convert_from_xy_to_rankfile($xy);

            $current_xy = $xy[$direction];
            $current_xy[0] =  $current_xy[0] * $spaces + $starting_square->rank;
            $current_xy[1] =  $current_xy[1] * $spaces + $starting_square->file;

            $square = $this->try_to_make_square_using_rank_and_file_num($current_xy[0], $current_xy[1]);

            if ( $square ) {
                array_push($list_of_squares, $square);
            }
        }

        if ( $list_of_squares === array() ) {
            $list_of_squares = NULL;
        }

        return $list_of_squares;
    }}

ChessMove.php

<?php

class ChessMove {
    const PIECE_LETTERS = array(
        'p' => 'pawn',
        'n' => 'knight',
        'b' => 'bishop',
        'r' => 'rook',
        'q' => 'queen',
        'k' => 'king'
    );

    var $starting_square;
    var $ending_square;
    var $color;
    var $piece_type;
    var $capture;
    var $check;
    var $checkmate;
    var $promotion_piece_type;
    var $en_passant_capture;
    var $disambiguation;

    var $notation;
    var $coordiante_notation;

    var $board;

    function __construct(
        $starting_square,
        $ending_square,
        $color,
        $piece_type,
        $capture,
        $old_board
    ) {
        $this->starting_square = $starting_square;
        $this->ending_square = $ending_square;
        $this->color = $color;
        $this->piece_type = $piece_type;
        $this->capture = $capture;

        // These cases are rare. The data is passed in via set functions instead of in the constructor.
        $this->disambiguation = '';
        $this->promotion_piece_type = NULL;
        $this->en_passant = FALSE;
        $this->check = FALSE;
        $this->checkmate = FALSE;

        $this->notation = $this->get_notation();
        $this->coordinate_notation = $this->starting_square->alphanumeric . $this->ending_square->alphanumeric;

        $this->board = clone $old_board;
        $this->board->make_move($starting_square, $ending_square);

        // if the king or rook moves, update the FEN to take away castling privileges
        if ( $this->color == 'black' ) {
            if (
                $this->piece_type == 'king' &&
                $this->starting_square->alphanumeric == 'e8'
            ) {
                $this->board->set_castling('black_can_castle_kingside', FALSE);
                $this->board->set_castling('black_can_castle_queenside', FALSE);
            } elseif (
                $this->piece_type == 'rook' &&
                $this->starting_square->alphanumeric == 'a8'
            ) {
                $this->board->set_castling('black_can_castle_queenside', FALSE);
            } elseif (
                $this->piece_type == 'rook' &&
                $this->starting_square->alphanumeric == 'h8'
            ) {
                $this->board->set_castling('black_can_castle_kingside', FALSE);
            }
        } elseif ( $this->color == 'white' ) {
            if (
                $this->piece_type == 'king' &&
                $this->starting_square->alphanumeric == 'e1'
            ) {
                $this->board->set_castling('white_can_castle_kingside', FALSE);
                $this->board->set_castling('white_can_castle_queenside', FALSE);
            } elseif (
                $this->piece_type == 'rook' &&
                $this->starting_square->alphanumeric == 'a1'
            ) {
                $this->board->set_castling('white_can_castle_queenside', FALSE);
            } elseif (
                $this->piece_type == 'rook' &&
                $this->starting_square->alphanumeric == 'h1'
            ) {
                $this->board->set_castling('white_can_castle_kingside', FALSE);
            }
        }

        // if castling, move the rook into the right place
        if ( $this->color == 'black' ) {
            if (
                $this->piece_type == 'king' &&
                $this->starting_square->alphanumeric == 'e8' &&
                $this->ending_square->alphanumeric == 'g8'
            ) {
                $starting_square = new ChessSquare('h8');
                $ending_square = new ChessSquare('f8');
                $this->board->make_additional_move_on_same_turn($starting_square, $ending_square);
            } elseif (
                $this->piece_type == 'king' &&
                $this->starting_square->alphanumeric == 'e8' &&
                $this->ending_square->alphanumeric == 'c8'
            ) {
                $starting_square = new ChessSquare('a8');
                $ending_square = new ChessSquare('d8');
                $this->board->make_additional_move_on_same_turn($starting_square, $ending_square);
            }
        } elseif ( $this->color == 'white' ) {
            if (
                $this->piece_type == 'king' &&
                $this->starting_square->alphanumeric == 'e1' &&
                $this->ending_square->alphanumeric == 'g1'
            ) {
                $starting_square = new ChessSquare('h1');
                $ending_square = new ChessSquare('f1');
                $this->board->make_additional_move_on_same_turn($starting_square, $ending_square);
            } elseif (
                $this->piece_type == 'king' &&
                $this->starting_square->alphanumeric == 'e1' &&
                $this->ending_square->alphanumeric == 'c1'
            ) {
                $starting_square = new ChessSquare('a1');
                $ending_square = new ChessSquare('d1');
                $this->board->make_additional_move_on_same_turn($starting_square, $ending_square);
            }
        }
    }

    // Do a deep clone. Needed for pawn promotion.
    function __clone() {
        $this->starting_square = clone $this->starting_square;
        $this->ending_square = clone $this->ending_square;
        $this->board = clone $this->board;
    }

    function set_promotion_piece($piece_type) {
        // update the piece
        $rank = $this->ending_square->rank;
        $file = $this->ending_square->file;
        $this->board->board[$rank][$file]->type = $piece_type;
        $this->board->update_fen();

        // Automatically pick queen when drag and dropping.
        if ( $piece_type != "queen" ) {
            $this->coordinate_notation = "";
        }

        // update the notation
        $this->promotion_piece_type = $piece_type;
        $this->notation = $this->get_notation();
    }

    function set_enemy_king_in_check($boolean) {
        $this->check = $boolean;

        $this->notation = $this->get_notation();
    }

    function set_checkmate($boolean) {
        $this->checkmate = $boolean;

        $this->notation = $this->get_notation();
    }

    function set_en_passant($boolean) {
        $this->en_passant = $boolean;

        $this->notation = $this->get_notation();
    }

    function set_disambiguation($string) {
        $this->disambiguation = $string;

        $this->notation = $this->get_notation();
    }

    function get_notation() {
        $string = '';

        if (
            $this->starting_square->alphanumeric == 'e8' &&
            $this->ending_square->alphanumeric == 'g8' &&
            $this->piece_type == 'king' &&
            $this->color = 'black'
        ) {
            $string .= 'O-O';
        } elseif (
            $this->starting_square->alphanumeric == 'e1' &&
            $this->ending_square->alphanumeric == 'g1' &&
            $this->piece_type == 'king' &&
            $this->color = 'white'
        ) {
            $string .= 'O-O';
        } elseif (
            $this->starting_square->alphanumeric == 'e8' &&
            $this->ending_square->alphanumeric == 'c8' &&
            $this->piece_type == 'king' &&
            $this->color = 'black'
        ) {
            $string .= 'O-O-O';
        } elseif (
            $this->starting_square->alphanumeric == 'e1' &&
            $this->ending_square->alphanumeric == 'c1' &&
            $this->piece_type == 'king' &&
            $this->color = 'white'
        ) {
            $string .= 'O-O-O';
        } else {
            // type of piece
            if ( $this->piece_type == 'pawn' && $this->capture ) {
                $string .= substr($this->starting_square->alphanumeric, 0, 1);
            } elseif ( $this->piece_type != 'pawn' ) {
                $string .= strtoupper(array_search(
                    $this->piece_type,
                    self::PIECE_LETTERS
                ));
            }

            // disambiguation rank/file/square
            $string .= $this->disambiguation;

            // capture?
            if ( $this->capture ) {
                $string .= 'x';
            }

            // destination square
            $string .= $this->ending_square->alphanumeric;

            // en passant
            if ( $this->en_passant ) {
                $string .= 'e.p.';
            }

            // pawn promotion
            if ( $this->promotion_piece_type == 'queen' ) {
                $string .= '=Q';
            } elseif ( $this->promotion_piece_type == 'rook' ) {
                $string .= '=R';
            } elseif ( $this->promotion_piece_type == 'bishop' ) {
                $string .= '=B';
            } elseif ( $this->promotion_piece_type == 'knight' ) {
                $string .= '=N';
            }
        }

        // check or checkmate
        if ( $this->checkmate ) {
            $string .= '#';
        } elseif ( $this->check ) {
            $string .= '+';
        }

        return $string;
    }
}

ChessBoard.php

<?php

class ChessBoard {
    const PIECE_LETTERS = array(
        'p' => 'pawn',
        'n' => 'knight',
        'b' => 'bishop',
        'r' => 'rook',
        'q' => 'queen',
        'k' => 'king'
    );

    var $board = array(); // $board[y][x], or in this case, $board[rank][file]
    var $color_to_move;
    var $castling = array(); // format is array('white_can_castle_kingside' => TRUE, etc.)
    var $en_passant_target_square = NULL;
    var $halfmove_clock;
    var $fullmove_number;

    var $fen;

    function __construct($fen) {
        $this->set_fen($fen);
        $this->fen = $fen;
    }

    function __clone() {
        if ( $this->board ) {
            for ( $rank = 1; $rank <= 8; $rank++ ) {
                for ( $file = 1; $file <= 8; $file++ ) {
                    if ( $this->board[$rank][$file] ) {
                        $this->board[$rank][$file] = clone $this->board[$rank][$file];
                    }
                }
            }
        }
    }

    function set_fen($fen) {
        $fen = trim($fen);

        // set everything back to default
        $legal_moves = array();
        $checkmate = FALSE;
        $stalemate = FALSE;
        $move_list = array();
        // TODO: add more

        // Basic format check. This won't catch everything, but it will catch a lot of stuff.
        // TODO: Make this stricter so that it catches everything.
        $valid_fen = preg_match('/^([rnbqkpRNBQKP12345678]{1,8})/([rnbqkpRNBQKP12345678]{1,8})/([rnbqkpRNBQKP12345678]{1,8})/([rnbqkpRNBQKP12345678]{1,8})/([rnbqkpRNBQKP12345678]{1,8})/([rnbqkpRNBQKP12345678]{1,8})/([rnbqkpRNBQKP12345678]{1,8})/([rnbqkpRNBQKP12345678]{1,8}) ([bw]{1}) ([-KQkq]{1,4}) ([a-h1-8-]{1,2}) (d{1,2}) (d{1,4})$/', $fen, $matches);

        if ( ! $valid_fen ) {
            throw new Exception('ChessBoard Class - Invalid FEN');
        }

        // ******* CREATE PIECES AND ASSIGN THEM TO SQUARES *******

        // Set all board squares to NULL. That way we don't have to blank them in the loop below. We can just overwrite the NULL with a piece.
        for ( $i = 1; $i <= 8; $i++ ) {
            for ( $j = 1; $j <= 8; $j++ ) {
                $this->board[$i][$j] = NULL;
            }
        }

        // Create $rank variables with strings that look like this
            // rnbqkbnr
            // pppppppp
            // 8
            // PPPPPPPP
            // RNBQKBNR
            // 2p5
        // The numbers are the # of blank squares from left to right
        $rank = array();
        for ( $i = 1; $i <= 8; $i++ ) {
            // Match string = 1, but rank = 8. Fix it here to avoid headaches.
            $rank = $this->invert_rank_or_file_number($i);
            $rank_string[$rank] = $matches[$i];
        }

        // Process $rank variable strings, convert to pieces and add them to $this->board[][]
        foreach ( $rank_string as $rank => $string ) {
            $file = 1;

            for ( $i = 1; $i <= strlen($string); $i++ ) {
                $char = substr($string, $i - 1, 1);

                // Don't use is_int here. $char is a string. Use is_numeric instead.
                if ( is_numeric($char) ) {
                    $file = $file + $char;
                } else {
                    $square = $this->number_to_file($file) . $rank;

                    if ( ctype_upper($char) ) {
                        $color = 'white';
                    } else {
                        $color = 'black';
                    }

                    $type = self::PIECE_LETTERS[strtolower($char)];

                    $this->board[$rank][$file] = new ChessPiece($color, $square, $type);

                    $file++;
                }
            }
        }

        // ******* SET COLOR TO MOVE *******
        if ( $matches[9] == 'w' ) {
            $this->color_to_move = 'white';
        } elseif ( $matches[9] == 'b' ) {
            $this->color_to_move = 'black';
        } else {
            throw new Exception('ChessBoard Class - Invalid FEN - Invalid Color To Move');
        }

        // Set all castling to false. Only set to true if letter is present in FEN. Prevents bugs.
        $this->castling['white_can_castle_kingside'] = FALSE;
        $this->castling['white_can_castle_queenside'] = FALSE;
        $this->castling['black_can_castle_kingside'] = FALSE;
        $this->castling['black_can_castle_queenside'] = FALSE;

        // ******* SET CASTLING POSSIBILITIES *******
        // strpos is case sensitive, so that's good
        if ( strpos($matches[10], 'K') !== FALSE ) {
            $this->castling['white_can_castle_kingside'] = TRUE;
        }

        if ( strpos($matches[10], 'Q') !== FALSE ) {
            $this->castling['white_can_castle_queenside'] = TRUE;
        }

        if ( strpos($matches[10], 'k') !== FALSE ) {
            $this->castling['black_can_castle_kingside'] = TRUE;
        }

        if ( strpos($matches[10], 'q') !== FALSE ) {
            $this->castling['black_can_castle_queenside'] = TRUE;
        }

        // ******* SET EN PASSANT TARGET SQUARE *******
        if ( $matches[11] == '-' ) {
            $this->en_passant_target_square = FALSE;
        } else {
            $this->en_passant_target_square = new ChessSquare($matches[11]);
        }
        // ChessPiece throws its own exceptions, so no need to throw one here.

        // ******* SET HALFMOVE CLOCK *******
        $this->halfmove_clock = $matches[12];

        // ******* SET FULLMOVE NUMBER *******
        $this->fullmove_number = $matches[13];

        // ******* SET HALFMOVE NUMBER *******
        $this->halfmove_number = $matches[13] * 2 - 1;
        if ( $this->color_to_move == 'black' ) {
            $this->halfmove_number++;
        }

        $this->fen = $fen;
    }

    function get_fen() {
        $string = '';

        // A chessboard looks like this
            // a8 b8 c8 d8
            // a7 b7 c7 d7
            // etc.
        // But we want to print them starting with row 8 first.
        // So we need to adjust the loops a bit.

        for ( $rank = 8; $rank >= 1; $rank-- ) {
            $empty_squares = 0;

            for ( $file = 1; $file <= 8; $file++ ) {
                $piece = $this->board[$rank][$file];

                if ( ! $piece ) {
                    $empty_squares++;
                } else {
                    if ( $empty_squares ) {
                        $string .= $empty_squares;
                        $empty_squares = 0;
                    }
                    $string .= $piece->get_fen_symbol();
                }
            }

            if ( $empty_squares ) {
                $string .= $empty_squares;
            }

            if ( $rank != 1 ) {
                $string .= "/";
            }
        }

        if ( $this->color_to_move == 'white' ) {
            $string .= " w ";
        } elseif ( $this->color_to_move == 'black' ) {
            $string .= " b ";
        }

        if ( $this->castling['white_can_castle_kingside'] ) {
            $string .= "K";
        }

        if ( $this->castling['white_can_castle_queenside'] ) {
            $string .= "Q";
        }

        if ( $this->castling['black_can_castle_kingside'] ) {
            $string .= "k";
        }

        if ( $this->castling['black_can_castle_queenside'] ) {
            $string .= "q";
        }

        if (
            ! $this->castling['white_can_castle_kingside'] &&
            ! $this->castling['white_can_castle_queenside'] &&
            ! $this->castling['black_can_castle_kingside'] &&
            ! $this->castling['black_can_castle_queenside']
        ) {
            $string .= "-";
        }

        if ( $this->en_passant_target_square ) {
            $string .= " " . $this->en_passant_target_square->alphanumeric;
        } else {
            $string .= " -";
        }

        $string .= " " . $this->halfmove_clock . ' ' . $this->fullmove_number;

        return $string;
    }

    function update_fen() {
        $this->fen = $this->get_fen();
    }

    // Keeping this for debug reasons.
    function get_ascii_board() {
        $string = '';

        if ( $this->color_to_move == 'white' ) {
            $string .= "White To Move";
        } elseif ( $this->color_to_move == 'black' ) {
            $string .= "Black To Move";
        }

        // A chessboard looks like this
            // a8 b8 c8 d8
            // a7 b7 c7 d7
            // etc.
        // But we want to print them starting with row 8 first.
        // So we need to adjust the loops a bit.

        for ( $rank = 8; $rank >= 1; $rank-- ) {
            $string .= "<br />";

            for ( $file = 1; $file <= 8; $file++ ) {
                $square = $this->board[$rank][$file];

                if ( ! $square ) {
                    $string .= "*";
                } else {
                    $string .= $this->board[$rank][$file]->get_unicode_symbol();
                }
            }
        }
        $string .= "<br /><br />";

        return $string;
    }

    function get_graphical_board() {
        // We need to throw some variables into an array so our view can build the board.
        // The array shall be in the following format:
            // square_color = black / white
            // id = a1-h8
            // piece = HTML unicode for that piece

        // A chessboard looks like this
            // a8 b8 c8 d8
            // a7 b7 c7 d7
            // etc.
        // But we want to print them starting with row 8 first.
        // So we need to adjust the loops a bit.

        $graphical_board_array = array();
        for ( $rank = 8; $rank >= 1; $rank-- ) {
            for ( $file = 1; $file <= 8; $file++ ) {
                $piece = $this->board[$rank][$file];

                // SQUARE COLOR
                if ( ($rank + $file) % 2 == 1 ) {
                    $graphical_board_array[$rank][$file]['square_color'] = 'white';
                } else {
                    $graphical_board_array[$rank][$file]['square_color'] = 'black';
                }

                // ID
                $file_letters = new Dictionary(array(
                    1 => 'a',
                    2 => 'b',
                    3 => 'c',
                    4 => 'd',
                    5 => 'e',
                    6 => 'f',
                    7 => 'g',
                    8 => 'h'
                ));
                $graphical_board_array[$rank][$file]['id'] = $file_letters->check_dictionary($file) . $rank;

                // PIECE
                if ( ! $piece ) {
                    $graphical_board_array[$rank][$file]['piece'] = '';
                } else {
                    $graphical_board_array[$rank][$file]['piece'] = $this->board[$rank][$file]->get_unicode_symbol();
                }
            }
        }

        return $graphical_board_array;
    }

    function get_side_to_move_string() {
        $string = '';

        if ( $this->color_to_move == 'white' ) {
            $string .= "White To Move";
        } elseif ( $this->color_to_move == 'black' ) {
            $string .= "Black To Move";
        }

        return $string;
    }

    function get_who_is_winning_string() {
        $points = 0;

        foreach ( $this->board as $key1 => $value1 ) {
            foreach ( $value1 as $key2 => $piece ) {
                if ( $piece ) {
                    $points += $piece->value;
                }
            }
        }

        if ( $points > 0 ) {
            return "Material: White Ahead By $points";
        } elseif ( $points < 0 ) {
            $points *= -1;
            return "Material: Black Ahead By $points";
        } else {
            return "Material: Equal";
        }
    }

    function invert_rank_or_file_number($number) {
        $dictionary = array(
            1 => 8,
            2 => 7,
            3 => 6,
            4 => 5,
            5 => 4,
            6 => 3,
            7 => 2,
            8 => 1
        );

        return $dictionary[$number];
    }

    function number_to_file($number) {
        $dictionary = array(
            1 => 'a',
            2 => 'b',
            3 => 'c',
            4 => 'd',
            5 => 'e',
            6 => 'f',
            7 => 'g',
            8 => 'h'
        );

        if ( ! array_key_exists($number, $dictionary) ) {
            throw new Exception('ChessBoard Class - number_to_file - unknown file number - $number = ' . var_export($number, TRUE));
        }

        return $dictionary[$number];
    }

    // Note: This does not check for and reject illegal moves. It is up to code in the ChessGame class to generate a list of legal moves, then only make_move those moves.
    // In fact, sometimes make_move will be used on illegal moves (king in check moves), then the illegal moves will be deleted from the list of legal moves in a later step.
    function make_move($old_square, $new_square) {
        $moving_piece = clone $this->board[$old_square->rank][$old_square->file];

        $this->set_en_passant_target_square(NULL);

        $is_capture = $this->board[$new_square->rank][$new_square->file];

        if (
            $moving_piece->type == 'pawn' ||
            $is_capture
        ) {
            $this->halfmove_clock = 0;
        } else {
            $this->halfmove_clock++;
        }

        $this->board[$new_square->rank][$new_square->file] = $moving_piece;

        // Update $moving_piece->square too to avoid errors.
        $moving_piece->square = $new_square;

        $this->board[$old_square->rank][$old_square->file] = NULL;

        if ( $this->color_to_move == 'black' ) {
            $this->fullmove_number++;
        }

        $this->flip_color_to_move();

        $this->update_fen();
    }

    // Used to move the rook during castling.
    // Can't use make_move because it messes up color_to_move, halfmove, and fullmove.
    function make_additional_move_on_same_turn($old_square, $new_square) {
        $moving_piece = clone $this->board[$old_square->rank][$old_square->file];

        $this->board[$new_square->rank][$new_square->file] = $moving_piece;

        // Update $moving_piece->square too to avoid errors.
        $moving_piece->square = $new_square;

        $this->board[$old_square->rank][$old_square->file] = NULL;

        $this->update_fen();
    }

    function flip_color_to_move() {
        if ( $this->color_to_move == 'white' ) {
            $this->color_to_move = 'black';
        } elseif ( $this->color_to_move == 'black' ) {
            $this->color_to_move = 'white';
        }
    }

    function set_castling($string, $boolean) {
        $this->castling[$string] = $boolean;
        $this->update_fen();
    }

    function set_en_passant_target_square($square) {
        $this->en_passant_target_square = $square;
        $this->update_fen();
    }

    function square_is_occupied($square) {
        $rank = $square->rank;
        $file = $square->file;

        if ( $this->board[$rank][$file] ) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    function get_king_square($color) {
        foreach ( $this->board as $key => $value ) {
            foreach ( $value as $key2 => $piece ) {
                if ( $piece ) {
                    if ( $piece->type == 'king' && $piece->color == $color ) {
                        return $piece->square;
                    }
                }
            }
        }

        return NULL;
    }

    function remove_piece_from_square($square) {
        $rank = $square->rank;
        $file = $square->file;

        $this->board[$rank][$file] = NULL;

        $this->update_fen();
    }
}

ChessPiece.php

<?php

class ChessPiece
{
    var $value;
    var $color;
    var $type;
    var $square;

    const VALID_COLORS = array('white', 'black');
    const VALID_TYPES = array('pawn', 'knight', 'bishop', 'rook', 'queen', 'king');
    const UNICODE_CHESS_PIECES = array(
        'white_king' => '♔',
        'white_queen' => '♕',
        'white_rook' => '♖',
        'white_bishop' => '♗',
        'white_knight' => '♘',
        'white_pawn' => '♙',
        'black_king' => '♚',
        'black_queen' => '♛',
        'black_rook' => '♜',
        'black_bishop' => '♝',
        'black_knight' => '♞',
        'black_pawn' => '♟'
    );
    const FEN_CHESS_PIECES = array(
        'white_king' => 'K',
        'white_queen' => 'Q',
        'white_rook' => 'R',
        'white_bishop' => 'B',
        'white_knight' => 'N',
        'white_pawn' => 'P',
        'black_king' => 'k',
        'black_queen' => 'q',
        'black_rook' => 'r',
        'black_bishop' => 'b',
        'black_knight' => 'n',
        'black_pawn' => 'p'
    );
    const PIECE_VALUES = array(
        'pawn' => 1,
        'knight' => 3,
        'bishop' => 3,
        'rook' => 5,
        'queen' => 9,
        'king' => 0
    );
    const SIDE_VALUES = array(
        'white' => 1,
        'black' => -1
    );

    function __construct($color, $square_string, $type) {
        if ( in_array($color, self::VALID_COLORS) ) {
            $this->color = $color;
        } else {
            throw new Exception('ChessPiece Class - Invalid Color');
        }

        $this->square = new ChessSquare($square_string);

        if ( in_array($type, self::VALID_TYPES) ) {
            $this->type = $type;
        } else {
            throw new Exception('ChessPiece Class - Invalid Type');
        }

        $this->value = self::PIECE_VALUES[$type] * self::SIDE_VALUES[$color];
    }

    function __clone() {
        $this->square = clone $this->square;
    }

    function get_unicode_symbol()
    {
        $dictionary_key = $this->color . '_' . $this->type;

        return self::UNICODE_CHESS_PIECES[$dictionary_key];
    }

    function get_fen_symbol()
    {
        $dictionary_key = $this->color . '_' . $this->type;

        return self::FEN_CHESS_PIECES[$dictionary_key];
    }

    function on_rank($rank)
    {
        if ( $rank == $this->square->rank ) {
            return TRUE;
        } else {
            return FALSE;
        }
    }
}

ChessSquare.php

<?php

class ChessSquare {
    const VALID_SQUARES = array(
        'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8',
        'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8',
        'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8',
        'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8',
        'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8',
        'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8',
        'g1', 'g2', 'g3', 'g4', 'g5', 'g6', 'g7', 'g8',
        'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8'
    );

    var $rank;
    var $file;
    var $alphanumeric;

    function __construct($alphanumeric) {
        $file_letters = new Dictionary(array(
            1 => 'a',
            2 => 'b',
            3 => 'c',
            4 => 'd',
            5 => 'e',
            6 => 'f',
            7 => 'g',
            8 => 'h'
        ));

        if ( in_array($alphanumeric, self::VALID_SQUARES) ) {
            $this->alphanumeric = $alphanumeric;

            $this->file = $file_letters->check_dictionary(substr($alphanumeric, 0, 1));
            $this->rank = substr($alphanumeric, 1, 1);
        } else {
            throw new Exception("ChessSquare Class - Invalid Square - $alphanumeric = " . var_export($alphanumeric, TRUE));
        }
    }
}

Dictionary.php

<?php

// Array of pairs. The list of both columns put together cannot contain duplicates.
class Dictionary {
    var $array_of_pairs;

    function __construct($array) {
        // make sure there are no duplicates

        $this->array_of_pairs = $array;
    }

    function check_dictionary($search_key) {
        if ( isset($this->array_of_pairs[$search_key]) ) {
            return $this->array_of_pairs[$search_key];
        } elseif ( $search_results = array_search($search_key, $this->array_of_pairs) ) {
            return $search_results;
        } else {
            return NULL;
        }
    }
}

script.js

$(document).ready(function(){
    $('select').dblclick(function(){
        $('#make_move').submit();
    });

    $('.draggable_piece').on("dragstart", function (event) {
        var dt = event.originalEvent.dataTransfer;
        dt.setData('Text', $(this).closest('td').attr('id'));
    });

    $('table td').on("dragenter dragover drop", function (event) {  
        event.preventDefault();

        if (event.type === 'drop') {
            var oldsquare = event.originalEvent.dataTransfer.getData('Text',$(this).attr('id'));

            var newsquare = $(this).attr('id');

            var coordinate_notation = oldsquare + newsquare;

            var option_tag_in_select_tag = $("select[name='move'] option[data-coordinate-notation='" + coordinate_notation + "']");

            if ( option_tag_in_select_tag.length != 0 ) {
                option_tag_in_select_tag.attr('selected','selected');

                $('#make_move').submit();
            }
        };
    });
})

style.css

body {
    font-family:sans-serif;
}

input[name="fen"] {
    width: 500px;
}

input[type="submit"],
input[type="button"] {
    font-size: 12pt;
}

textarea[name="pgn"] {
    width: 500px;
    font-family: sans-serif;
}

select[name="move"] {
    width: 8em;
}

.two_columns {
    display: flex;
    width: 600px;
}

.two_columns>div:nth-child(1) {
    flex: 60%;
}

.two_columns>div:nth-child(2) {
    flex: 40%;
}

#graphical_board {
    table-layout: fixed;
    border-collapse: collapse;
}

#graphical_board td {
    height: 40px;
    width: 40px;
    padding: 0;
    margin: 0;
    text-align: center;
    vertical-align: middle;
    font-size: 30px;
    font-weight: bold;
    font-family: "Arial Unicode MS", "Lucida Console", Courier, monospace;
    cursor: move;
}

.black {
    background-color: #769656;
}

.white {
    background-color: #EEEED2;
}

.status_box {
    background-color: #F0F0F0;
    border: 1px solid black;
    padding-top: 2px;
    padding-bottom: 2px;
    padding-left: 4px;
    padding-right: 4px;
    width: 310px;
    margin-bottom: 5px;
}

view.php

<!DOCTYPE html>

<html lang="en-us">
    <head>
        <meta charset="utf-8" />

        <title>
            AdmiralAdama Chess
        </title>

        <link rel="stylesheet" href="style.css">

        https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js

        http://scripts.js
    </head>

    <body>
        <h1>
        AdmiralAdama Chess
        </h1>

        
<table id="graphical_board"> <tbody> <?php foreach ( $graphical_board_array as $rank => $row ): ?> <tr> <?php foreach ( $row as $file => $column ): ?> <td id ="<?php echo $column['id']; ?>" class="<?php echo $column['square_color']; ?>" > <span class="draggable_piece" draggable="true" > <?php echo $column['piece']; ?> </span> </td> <?php endforeach; ?> </tr> <?php endforeach; ?> </tbody> </table> <!-- <input type="submit" name="flip" value="Flip The Board" /> --> <input type="button" onclick="window.location='.'" value="Reset The Board" /> </div>
Legal Moves:
$move ): ?> board->fen; ?>" data-coordinate-notation="coordinate_notation; ?>" > notation; ?>
Move Count:
Load Time: ms
</div> <form id="import_fen"> <p> FEN:<br /> <input type="text" name="fen" value="<?php echo $fen; ?>" /><br /> <input type="submit" value="Import FEN" /> </p> </form> </body> </html>


Get this bounty!!!

#StackBounty: #php #wordpress #apache #server Understand apache setings for webpage with more requests

Bounty: 50

I have a wordpress site that has around 200 requests on home page including js, css, images etc. I am using default apache setting of minSpare Server as 5, max spare as 10, MaxRequestWorkers 150, Max child Per Request 0.

I need to understand what these settings are and what should be my ideal settings considering 10 concurrent users on home page. I am operating on a T2 medium instance on AWS. Database is on RDS. The average per apache process consumes around 120MB of RAM. I know, I should use cdn, but I need to understand apache behaviour with my current standings.


Get this bounty!!!

#StackBounty: #magento-1.9 #php Magento add position 999 when assign product to category

Bounty: 50

I’m using Magento 1.9.x and trying to change default position number of products.

Ex, when we assign product to category via product page i need to set it to 999 position

enter image description here

I changed default position field value of catalog_category_product table

enter image description here

But nothing changed.

i changed magentoappcodecoreMageCatalogModelResourceCategory.php

/**
         * Add products to category
         */
        if (!empty($insert)) {
            $data = array();
            foreach ($insert as $productId => $position) {
                $data[] = array(
                    'category_id' => (int)$id,
                    'product_id'  => (int)$productId,
                    'position'    =>  (int)$position ? (int)$position : 999
                );
            }
            //(int)$position
            $adapter->insertMultiple($this->_categoryProductTable, $data);
        }

but it only effect when adding products to category via category page.

anyone know a solution for this please, Thank You


Get this bounty!!!

#StackBounty: #c# #php c# MCRYPT_RIJNDAEL_256 Encryption Decryption Class in php

Bounty: 50

I am trying to convert c# application into php but I stuck at a place where C# provides Security class for Encryption and decryption based on RIJNDAEL algo. I am trying to convert into php.

Note: I am Using php 7.2 so mcrypt is deprecated for this version.

C# code

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace pharmarackencryption
{
    class Program
    {
        private const string initVector = "aw90rela942f65u2";

        // This constant is used to determine the keysize of the encryption algorithm.
        private const int keysize = 256;

        public static string Encrypt(string plainText, string passPhrase = "testing")
        {
            byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector);
            byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
            PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
            byte[] keyBytes = password.GetBytes(keysize / 8);
            RijndaelManaged symmetricKey = new RijndaelManaged();
            symmetricKey.Mode = CipherMode.CBC;
            ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
            cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
            cryptoStream.FlushFinalBlock();
            byte[] cipherTextBytes = memoryStream.ToArray();
            memoryStream.Close();
            cryptoStream.Close();
            return Convert.ToBase64String(cipherTextBytes);
        }

        public static string Decrypt(string cipherText, string passPhrase = "testing")
        {
            byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
            byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
            PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null);
            byte[] keyBytes = password.GetBytes(keysize / 8);
            RijndaelManaged symmetricKey = new RijndaelManaged();
            symmetricKey.Mode = CipherMode.CBC;
            ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
            MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
            CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
            byte[] plainTextBytes = new byte[cipherTextBytes.Length];
            int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
            memoryStream.Close();
            cryptoStream.Close();
            return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            string enc_password = Encrypt("437217");
            string dec_password = Decrypt("C9xJGa03dRQx9ePm0nLnHg==");
            Console.WriteLine(enc_password);
            Console.WriteLine(dec_password);
        }
    }
}

Encryption : C9xJGa03dRQx9ePm0nLnHg==

I found some what similar code in php like

PHP code:

<?php 
    // key/iv in ASCII binary data, $str base64
    function decrypt_stuff($key, $str, $iv) {
        // $plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($str), MCRYPT_MODE_CBC, $iv);
        $plaintext_dec = openssl_decrypt(base64_decode($str), "aes-256-cbc", $key,  OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
        return $plaintext_dec;
    }

    // key/iv in ascii binary data, $str ascii
    function encrypt_stuff($key, $str, $iv) {
        // $ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $str, MCRYPT_MODE_CBC, $iv));
        if (($l = (strlen($str) & 15)) > 0) { $str .= str_repeat(chr(0), 16 - $l); }
        $ciphertext = base64_encode(openssl_encrypt($str, "aes-256-cbc", $key,  OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv));
        return $ciphertext;
    }

    echo encrypt_stuff("testing","437217","aw90rela942f65u2");
    //Result : LTbhEHjFgfa5PDJQXJEdKQ==

Both are going same thing but still result is different


Get this bounty!!!

#StackBounty: #apache-httpd #php Apache and FPM link severed by script timeout

Bounty: 100

I am attempting to setup Apache + PHP-FPM, however, we have a long running script that was executed and eventually timed out, which severed the link between Apache and FPM ultimately bringing down the whole site…

Is there anyway to prevent the whole site from coming down if the –idle-timeout is reached?

FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -idle-timeout 18000 -pass-header Authorization


Get this bounty!!!