<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ivijan-Stefan Stipić</title>
    <description>The latest articles on DEV Community by Ivijan-Stefan Stipić (@ivijanstefanstipic).</description>
    <link>https://dev.to/ivijanstefanstipic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4104077%2Ffba2a725-63eb-4ced-8139-75c37c6967a0.png</url>
      <title>DEV Community: Ivijan-Stefan Stipić</title>
      <link>https://dev.to/ivijanstefanstipic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ivijanstefanstipic"/>
    <language>en</language>
    <item>
      <title>Running Legacy PHP on PHP 8</title>
      <dc:creator>Ivijan-Stefan Stipić</dc:creator>
      <pubDate>Tue, 01 Sep 2026 20:01:59 +0000</pubDate>
      <link>https://dev.to/ivijanstefanstipic/running-legacy-php-on-php-8-31ek</link>
      <guid>https://dev.to/ivijanstefanstipic/running-legacy-php-on-php-8-31ek</guid>
      <description>&lt;p&gt;Upgrading a modern PHP application is usually a controlled process. You update dependencies, run tests, fix deprecations, and deploy the new runtime.&lt;/p&gt;

&lt;p&gt;Legacy PHP applications are rarely that simple.&lt;/p&gt;

&lt;p&gt;They may contain abandoned packages, custom business logic, old WordPress plugins, legacy framework code, and functionality written long before Composer became standard. When the server moves to PHP 8, the application can stop immediately because it still calls functions such as &lt;code&gt;create_function()&lt;/code&gt;, &lt;code&gt;each()&lt;/code&gt;, &lt;code&gt;ereg()&lt;/code&gt;, or &lt;code&gt;split()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is why I built &lt;a href="https://github.com/InfinitumForm/php-legacy-compat" rel="noopener noreferrer"&gt;PHP Legacy Compat&lt;/a&gt;, an open-source PHP 8 compatibility layer for applications originally written for PHP 5.x and PHP 7.x.&lt;/p&gt;

&lt;p&gt;The project does not make legacy code modern. It provides enough stability to keep an application operational while the underlying code is upgraded properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The migration gap
&lt;/h2&gt;

&lt;p&gt;The correct long-term solution for removed PHP functionality is to rewrite the affected code. In production, however, a full rewrite may not be possible before an infrastructure deadline.&lt;/p&gt;

&lt;p&gt;An internal CRM may contain undocumented business rules. A WordPress website may depend on an abandoned theme. A Magento 1 integration may still process orders. Keeping an unsupported PHP runtime online is risky, but replacing the entire application immediately may be equally unrealistic.&lt;/p&gt;

&lt;p&gt;PHP Legacy Compat is intended for the space between those two problems.&lt;/p&gt;

&lt;p&gt;It provides polyfills, documented approximations, and safer helpers for common migration failures, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;create_function()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;each()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ereg()&lt;/code&gt;, &lt;code&gt;eregi()&lt;/code&gt; and related POSIX regex functions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;split()&lt;/code&gt; and &lt;code&gt;spliti()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;legacy session registration functions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;utf8_encode()&lt;/code&gt; and &lt;code&gt;utf8_decode()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;deprecated &lt;code&gt;strftime()&lt;/code&gt; behavior&lt;/li&gt;
&lt;li&gt;unsafe &lt;code&gt;count()&lt;/code&gt; calls&lt;/li&gt;
&lt;li&gt;the old reversed argument order for &lt;code&gt;implode()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, old code may still contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;create_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'$value'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'return trim($value);'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;process_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On PHP 8, both examples fail because those functions no longer exist. The compatibility layer restores practical behavior so the application can continue running while these calls are replaced with closures, &lt;code&gt;foreach&lt;/code&gt;, and other modern alternatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compatibility must be honest
&lt;/h2&gt;

&lt;p&gt;The easiest way to hide migration errors would be to define every missing function and return a harmless-looking value. That approach is dangerous because it can silently break business logic or corrupt data.&lt;/p&gt;

&lt;p&gt;PHP Legacy Compat follows a simple rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Compatibility must be honest.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The project distinguishes between true polyfills, partial polyfills, safe fallbacks, and compatibility approximations.&lt;/p&gt;

&lt;p&gt;Some behavior, such as &lt;code&gt;each()&lt;/code&gt;, can be reproduced closely. Other behavior depended on engine internals that no longer exist. The old POSIX regex functions, for example, must be approximated using PCRE, so their limitations are documented rather than hidden.&lt;/p&gt;

&lt;p&gt;The project does not attempt to recreate removed extension stacks such as &lt;code&gt;ext/mysql&lt;/code&gt; or &lt;code&gt;ext/mcrypt&lt;/code&gt;. It does not provide fake cryptography, pretend that magic quotes still exist, or return fake success values just to prevent an error.&lt;/p&gt;

&lt;p&gt;If behavior cannot be restored safely or meaningfully in userland, the library does not pretend otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Universal and Strict modes
&lt;/h2&gt;

&lt;p&gt;Different migrations require different levels of compatibility, so the project provides two mutually exclusive files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Universal mode
&lt;/h3&gt;

&lt;p&gt;Universal mode offers broader compatibility for difficult migrations where keeping the application operational is the immediate priority.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/php-legacy-compat-universal.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It includes carefully documented approximations where they remain useful. This mode is usually the practical starting point for an old application with many runtime failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strict mode
&lt;/h3&gt;

&lt;p&gt;Strict mode provides a narrower and more conservative compatibility surface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/php-legacy-compat-strict.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It excludes looser behavior where the risk of semantic differences is higher. It is useful when an application is already partly modernized or when a team wants fewer approximations.&lt;/p&gt;

&lt;p&gt;Only one mode should be loaded during a request. The two files represent different migration policies and are intentionally not loaded automatically by Composer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;The package is available through Composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require infinitumform/php-legacy-compat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then include one compatibility file as early as possible in the application bootstrap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/vendor/infinitumform/php-legacy-compat/php-legacy-compat-universal.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the application, this can be loaded from a front controller, bootstrap file, framework entry point, or WordPress must-use plugin.&lt;/p&gt;

&lt;p&gt;For WordPress, a small loader can run before an old theme or normal plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cd"&gt;/**
 * Plugin Name: Legacy PHP 8 Compatibility Loader
 */&lt;/span&gt;

&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="no"&gt;WPMU_PLUGIN_DIR&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/php-legacy-compat-universal.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project is not limited to WordPress. It can also help with legacy Laravel, Symfony, CodeIgniter, Magento, custom frameworks, and internal PHP systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration helpers and diagnostics
&lt;/h2&gt;

&lt;p&gt;Some PHP 8 problems cannot be solved by redefining a removed function. &lt;code&gt;count()&lt;/code&gt; still exists, but it no longer accepts every loose value that legacy code may pass.&lt;/p&gt;

&lt;p&gt;For those cases, the project provides explicit helpers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;legacy_safe_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;process_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The historical reversed argument order for &lt;code&gt;implode()&lt;/code&gt; can be handled during migration with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;legacy_safe_implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A diagnostic report is also available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;legacy_compat_get_report&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$report&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reports the active mode, available polyfills, helpers, and notable limitations. An optional soft error handler is included for controlled staging, but it is disabled by default and should not replace proper error handling or real fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  A bridge, not a permanent fix
&lt;/h2&gt;

&lt;p&gt;My recommended migration path is straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load Universal mode to get a difficult legacy application running on PHP 8.&lt;/li&gt;
&lt;li&gt;Test critical workflows and identify remaining incompatibilities.&lt;/li&gt;
&lt;li&gt;Replace restored legacy calls with modern PHP code.&lt;/li&gt;
&lt;li&gt;Move to Strict mode to expose dependencies on looser behavior.&lt;/li&gt;
&lt;li&gt;Remove the compatibility layer when the application no longer needs it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That final removal is a successful outcome. The project is designed to make itself unnecessary over time.&lt;/p&gt;

&lt;p&gt;No userland library can reproduce every detail of an old PHP runtime. It cannot repair unrelated security problems, replace framework upgrades, or guarantee that an application behaves correctly without testing. The current project scope explicitly targets PHP 8.0 through PHP 8.3.&lt;/p&gt;

&lt;p&gt;What it can do is prevent removed functions from blocking the entire migration, clearly document unavoidable differences, and provide developers with enough time to modernize a codebase in controlled steps.&lt;/p&gt;

&lt;p&gt;PHP Legacy Compat is open source and released under the MIT License:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/InfinitumForm/php-legacy-compat" rel="noopener noreferrer"&gt;github.com/InfinitumForm/php-legacy-compat&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Legacy software does not always need to be preserved forever, but it often needs a safe path forward. This project is intended to provide that path.&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>wordpress</category>
      <category>legacy</category>
    </item>
    <item>
      <title>How I Built AIVISO for AI Image Disclosure in WordPress</title>
      <dc:creator>Ivijan-Stefan Stipić</dc:creator>
      <pubDate>Tue, 01 Sep 2026 10:48:51 +0000</pubDate>
      <link>https://dev.to/ivijanstefanstipic/how-i-built-aiviso-for-ai-image-disclosure-in-wordpress-4p9b</link>
      <guid>https://dev.to/ivijanstefanstipic/how-i-built-aiviso-for-ai-image-disclosure-in-wordpress-4p9b</guid>
      <description>&lt;p&gt;AI-generated and AI-modified images are becoming common across blogs, news websites, online stores, and other publishing platforms. However, visitors often have no clear way to know whether an image was created or changed using AI.&lt;/p&gt;

&lt;p&gt;I built AIVISO to provide WordPress publishers with a simple and transparent way to disclose this information.&lt;/p&gt;

&lt;h2&gt;
  
  
  What AIVISO Does
&lt;/h2&gt;

&lt;p&gt;AIVISO adds disclosure information directly to images managed through WordPress. Publishers can mark an image as AI-generated or AI-modified and provide additional details about its origin and review process.&lt;/p&gt;

&lt;p&gt;The plugin supports information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disclosure type&lt;/li&gt;
&lt;li&gt;Source URL&lt;/li&gt;
&lt;li&gt;Creation or modification date&lt;/li&gt;
&lt;li&gt;Review date&lt;/li&gt;
&lt;li&gt;Reviewer information&lt;/li&gt;
&lt;li&gt;Custom disclosure details&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A visible badge can be displayed with disclosed images, allowing visitors to open the available information. AIVISO can also generate publisher-supplied Schema.org JSON-LD for disclosed images.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built It
&lt;/h2&gt;

&lt;p&gt;My goal was not to detect AI-generated content automatically. Detection tools can produce inaccurate results, especially as image-generation technology continues to improve.&lt;/p&gt;

&lt;p&gt;Instead, AIVISO is based on publisher disclosure. The person or organization publishing the image provides the relevant information and remains responsible for its accuracy.&lt;/p&gt;

&lt;p&gt;This approach keeps the plugin transparent, predictable, and independent of external AI detection services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for WordPress
&lt;/h2&gt;

&lt;p&gt;AIVISO integrates with the WordPress media workflow and can be enabled only for selected post types. Disclosure information remains manageable from the WordPress administration area without requiring a separate platform or external account.&lt;/p&gt;

&lt;p&gt;The plugin is free and open source, and it is intended for publishers who want to introduce clearer AI content practices before disclosure becomes a mandatory part of their workflow.&lt;/p&gt;

&lt;p&gt;You can download AIVISO from the official WordPress plugin directory:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wordpress.org/plugins/aiviso-ai-image-disclosure/" rel="noopener noreferrer"&gt;https://wordpress.org/plugins/aiviso-ai-image-disclosure/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
      <category>eu</category>
      <category>aiviso</category>
    </item>
  </channel>
</rss>
