{"id":303026,"date":"2026-06-19T08:31:49","date_gmt":"2026-06-19T08:31:49","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/i-downloads\/"},"modified":"2026-06-21T20:59:21","modified_gmt":"2026-06-21T20:59:21","slug":"isoft-fm-foundation","status":"publish","type":"plugin","link":"https:\/\/ast.wordpress.org\/plugins\/isoft-fm-foundation\/","author":23483774,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.11.0","stable_tag":"0.11.0","tested":"7.0","requires":"6.7","requires_php":"8.4","requires_plugins":null,"header_name":"I-Soft File Manager: Foundation","header_author":"I-SOFT Mionica","header_description":"Hierarchical file download manager \u2014 categories, multi-file entries, secure download handler, audit logging, and role-based access control.","assets_banners_color":"","last_updated":"2026-06-21 20:59:21","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/github.com\/I-SOFT-Mionica\/isoft-fm-foundation","header_author_uri":"https:\/\/github.com\/I-SOFT-Mionica","rating":0,"author_block_rating":0,"active_installs":0,"downloads":121,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.10.17":{"tag":"0.10.17","author":"chillic","date":"2026-06-19 08:31:23"},"0.10.18":{"tag":"0.10.18","author":"chillic","date":"2026-06-20 12:26:45"},"0.11.0":{"tag":"0.11.0","author":"chillic","date":"2026-06-21 20:59:21"}},"upgrade_notice":{"0.11.0":"<p>License inheritance from categories. Two new seeded licenses (Serbian PD, CC BY-SA 4.0). License chip on cards. Download log records its license. Click Restore seeded licenses on Downloads \u2192 Licenses. Known: assign one category per download \u2014 picker fix in next patch.<\/p>","0.10.21":"<p>Fix for a misleading lock icon shown on publicly accessible files that inherited their access role from a category with no default set. Otherwise routine.<\/p>","0.10.20":"<p>HOT downloads and the Top Downloads dashboard panel now work on new and low-traffic sites (silent fallback to all-time when there&#039;s no recent data). The 30-day chart and panel now actually cover 30 days of data instead of 8.<\/p>","0.10.19":"<p>If the plugin appeared to install but your uploads kept failing with &quot;Could not save file record,&quot; this release surfaces the underlying cause (usually a missing database privilege) and gives you the SQL to fix it. Otherwise routine.<\/p>"},"ratings":[],"assets_icons":{"icon-256x256.png":{"filename":"icon-256x256.png","revision":3578249,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3578249,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3578249,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":{"isoft-fm-foundation\/category-grid":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"isoft-fm-foundation\/category-grid","version":"0.1.0","title":"Download Category Grid [iD]","category":"isoft-fm-foundation","icon":"grid-view","description":"Display download categories as a grid.","textdomain":"isoft-fm-foundation","supports":{"html":false,"color":true,"spacing":true},"attributes":{"parent":{"type":"number","default":0},"columns":{"type":"number","default":3},"showCount":{"type":"boolean","default":true},"showDescription":{"type":"boolean","default":true}},"editorScript":"file:..\/build\/category-grid.js","render":"file:.\/render.php"},"isoft-fm-foundation\/download-button":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"isoft-fm-foundation\/download-button","version":"0.1.0","title":"Download Entry [iD]","category":"isoft-fm-foundation","icon":"download","description":"Embed the full download card for a selected download entry.","textdomain":"isoft-fm-foundation","supports":{"html":false,"color":true,"typography":true,"spacing":true},"attributes":{"downloadId":{"type":"number","default":0}},"editorScript":"file:..\/build\/download-button.js","render":"file:.\/render.php"},"isoft-fm-foundation\/download-list":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"isoft-fm-foundation\/download-list","version":"0.1.0","title":"Download List [iD]","category":"isoft-fm-foundation","icon":"download","description":"Display a list of downloads, optionally filtered by category or tag.","textdomain":"isoft-fm-foundation","supports":{"html":false,"color":true,"typography":true,"spacing":true},"attributes":{"category":{"type":"number","default":0},"includeSubcategories":{"type":"boolean","default":true},"tag":{"type":"number","default":0},"limit":{"type":"number","default":10},"orderby":{"type":"string","default":"date"},"order":{"type":"string","default":"DESC"},"layout":{"type":"string","default":"list"},"showSearch":{"type":"boolean","default":false}},"editorScript":"file:..\/build\/download-list.js","render":"file:.\/render.php"}},"tagged_versions":["0.10.17","0.10.18","0.11.0"],"block_files":[],"assets_screenshots":{"screenshot-1.jpg":{"filename":"screenshot-1.jpg","revision":3578249,"resolution":"1","location":"assets","locale":"","width":1901,"height":813},"screenshot-2.jpg":{"filename":"screenshot-2.jpg","revision":3578249,"resolution":"2","location":"assets","locale":"","width":510,"height":673},"screenshot-3.jpg":{"filename":"screenshot-3.jpg","revision":3578249,"resolution":"3","location":"assets","locale":"","width":1916,"height":858},"screenshot-4.jpg":{"filename":"screenshot-4.jpg","revision":3578249,"resolution":"4","location":"assets","locale":"","width":1761,"height":798},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3578249,"resolution":"5","location":"assets","locale":"","width":1753,"height":725}},"screenshots":{"1":"Download edit screen with drag-and-drop upload, per-file progress, and the From Folder browser.","2":"Download list block in grid mode \u2014 portrait tiles with file-type badges.","3":"Per-user category ACL tree on the profile screen.","4":"Statistics dashboard with HOT downloads and per-file counts.","5":"Download handler settings \u2014 security, logging, and serve method."}},"plugin_section":[],"plugin_tags":[610,12813,18284,5440,8848],"plugin_category":[57],"plugin_contributors":[267847],"plugin_business_model":[],"class_list":["post-303026","plugin","type-plugin","status-publish","hentry","plugin_tags-categories","plugin_tags-document-management","plugin_tags-download-counter","plugin_tags-downloads","plugin_tags-file-manager","plugin_category-taxonomy","plugin_contributors-chillic","plugin_committers-chillic"],"banners":{"banner":"https:\/\/ps.w.org\/isoft-fm-foundation\/assets\/banner-772x250.png?rev=3578249","banner_2x":"https:\/\/ps.w.org\/isoft-fm-foundation\/assets\/banner-1544x500.png?rev=3578249","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/isoft-fm-foundation\/assets\/icon-256x256.png?rev=3578249","icon_2x":"https:\/\/ps.w.org\/isoft-fm-foundation\/assets\/icon-256x256.png?rev=3578249","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/isoft-fm-foundation\/assets\/screenshot-1.jpg?rev=3578249","caption":"Download edit screen with drag-and-drop upload, per-file progress, and the From Folder browser."},{"src":"https:\/\/ps.w.org\/isoft-fm-foundation\/assets\/screenshot-2.jpg?rev=3578249","caption":"Download list block in grid mode \u2014 portrait tiles with file-type badges."},{"src":"https:\/\/ps.w.org\/isoft-fm-foundation\/assets\/screenshot-3.jpg?rev=3578249","caption":"Per-user category ACL tree on the profile screen."},{"src":"https:\/\/ps.w.org\/isoft-fm-foundation\/assets\/screenshot-4.jpg?rev=3578249","caption":"Statistics dashboard with HOT downloads and per-file counts."},{"src":"https:\/\/ps.w.org\/isoft-fm-foundation\/assets\/screenshot-5.png?rev=3578249","caption":"Download handler settings \u2014 security, logging, and serve method."}],"raw_content":"<!--section=description-->\n<p><strong>I-Soft File Manager: Foundation<\/strong> is a modular download manager built for modern WordPress.<\/p>\n\n<p>Unlike standard media plugins that dump every upload into a single dated folder, Foundation is designed for municipalities, universities, libraries, and any team that needs to manage thousands of public documents, maintain a strict category tree, and give different departments their own secure upload spaces.<\/p>\n\n<h4>Key features<\/h4>\n\n<ul>\n<li><strong>True folder organization.<\/strong> Every category you create maps 1:1 to a real folder on disk under <code>wp-content\/uploads\/isoft-fmf-files\/<\/code>. Rename a category and the folder renames itself; every file path in the database updates instantly.<\/li>\n<li><strong>Department-level access control.<\/strong> Restrict editors to specific categories so HR uploads only land in the HR folder, IT uploads only in the IT folder, and so on. Restricted users cannot see drafts from other departments either.<\/li>\n<li><strong>External file sync and \"From Folder\" browser.<\/strong> Because categories are real folders, drop files into them via SFTP, rclone, or any external sync tool. The From Folder browser detects untracked files instantly so you can link them to a download with one click.<\/li>\n<li><strong>One-click multi-file downloads.<\/strong> Upload multiple files to a single entry via drag-and-drop. Visitors can grab individual files or everything at once as an automatically generated ZIP bundle.<\/li>\n<li><strong>Built-in analytics and audit log.<\/strong> Statistics dashboard tracks per-file and aggregate counts, recalculates HOT badges nightly, and the optional audit log records timestamps, IP addresses, and user agents with configurable retention.<\/li>\n<li><strong>Secure download handler.<\/strong> Files live behind an <code>.htaccess<\/code>-protected directory; every download routes through PHP with nonce verification, role checks, rate limiting, and hotlink protection. X-Sendfile and X-Accel-Redirect supported for high-traffic hosts.<\/li>\n<li><strong>Cyrillic transliteration.<\/strong> Uploaded filenames and category slugs are automatically transliterated from Serbian Cyrillic to Latin for safe disk storage; display titles keep their original characters.<\/li>\n<li><strong>Native builder support.<\/strong> Gutenberg blocks ship out of the box. Eight shortcodes work in Elementor, WPBakery, Divi, Beaver Builder, and Bricks \u2014 see the <a href=\"#shortcodes\">full shortcode reference<\/a> below.<\/li>\n<li><strong>Themeable via CSS variables.<\/strong> Recolor every card, badge, and icon from <strong>Appearance \u2192 Customize \u2192 Additional CSS<\/strong> without writing complex selectors \u2014 see <a href=\"#customizing-appearance\">customizing appearance<\/a> below.<\/li>\n<\/ul>\n\n<h4>Architecture in one line<\/h4>\n\n<p>The filesystem <strong>is<\/strong> the source of truth. Moving a download to a different category auto-moves its files on disk; deleting a category is blocked if any download still references it. This is what lets external automation tools sync files in and out without having to understand WordPress internals.<\/p>\n\n<h4>Extensions (coming soon)<\/h4>\n\n<ul>\n<li><strong>I-Soft File Manager: Sentinel<\/strong> \u2014 server-side automation. Monitors category folders for new files, creates draft download entries, and supports rclone mirroring, SFTP bulk upload, and scheduled folder scans.<\/li>\n<li><strong>I-Soft File Manager: Orbit<\/strong> \u2014 Google Shared Drive sync. Departments drop files into shared folders; Orbit imports them as drafts for review.<\/li>\n<li><strong>I-Soft File Manager: Arbiter<\/strong> \u2014 one-shot importer from jDownloads. Rebuilds your categories, downloads, files, and counters in Foundation, preserving slug paths so existing URLs keep working.<\/li>\n<\/ul>\n\n<h3>Shortcodes<\/h3>\n\n<p>Foundation ships eight shortcodes. Drop them in any classic-editor page, any Gutenberg \"Shortcode\" block, or any builder's HTML \/ Shortcode widget. Every <code>category<\/code> and <code>tag<\/code> attribute accepts either the term <strong>slug<\/strong> (preferred \u2014 stable across exports) or its numeric <strong>term ID<\/strong>. Slugs are visible on the Downloads \u2192 Categories screen and as the chip next to the category name on the download edit screen.<\/p>\n\n<h4>[isoft_fmf_list] \u2014 filtered list of downloads<\/h4>\n\n<p>Renders a grid, list, or table of downloads. Same renderer as the Download List block.<\/p>\n\n\n\n\n  Attribute\n  Default\n  What\n\n\n\n\n  <code>category<\/code>\n  empty\n  slug or term ID; empty = all categories\n\n\n  <code>include_subcategories<\/code>\n  <code>\"1\"<\/code>\n  also include downloads in descendant categories; <code>\"0\"<\/code> restricts to the exact category\n\n\n  <code>tag<\/code>\n  empty\n  slug or term ID\n\n\n  <code>limit<\/code>\n  per-page setting\n  how many to render\n\n\n  <code>orderby<\/code>\n  <code>\"date\"<\/code>\n  <code>date<\/code> \/ <code>title<\/code> \/ <code>download_count<\/code> \/ any WP_Query orderby\n\n\n  <code>order<\/code>\n  <code>\"DESC\"<\/code>\n  <code>ASC<\/code> \/ <code>DESC<\/code>\n\n\n  <code>layout<\/code>\n  display setting\n  <code>grid<\/code> \/ <code>list<\/code> \/ <code>table<\/code>\n\n\n  <code>show_search<\/code>\n  <code>\"0\"<\/code>\n  render a search box scoped to the same category\n\n\n\n\n<p>Common recipes:<\/p>\n\n<pre><code>[isoft_fmf_list category=\"resolutions\"]\n[isoft_fmf_list category=\"resolutions\" layout=\"grid\" limit=\"12\"]\n[isoft_fmf_list category=\"resolutions\" orderby=\"download_count\"]\n[isoft_fmf_list category=\"resolutions\" show_search=\"1\"]\n<\/code><\/pre>\n\n<h4>[isoft_fmf_download id=\"123\"] \u2014 a single download card<\/h4>\n\n<p>Renders one download's full card by post ID.<\/p>\n\n\n\n\n  Attribute\n  Default\n  What\n\n\n\n\n  <code>id<\/code>\n  required\n  the download post ID\n\n\n  <code>show_description<\/code>\n  <code>\"1\"<\/code>\n  include the description below the title\n\n\n  <code>show_files<\/code>\n  <code>\"1\"<\/code>\n  render the per-file list with download buttons\n\n\n  <code>style<\/code>\n  <code>\"card\"<\/code>\n  <code>card<\/code> \/ <code>compact<\/code> \/ <code>button-only<\/code>\n\n\n\n\n<h4>[isoft_fmf_categories] \u2014 category grid<\/h4>\n\n<p>Clickable cards leading to each category's archive page. Same renderer as the Category Grid block.<\/p>\n\n\n\n\n  Attribute\n  Default\n  What\n\n\n\n\n  <code>parent<\/code>\n  <code>0<\/code>\n  term ID of the parent category to show children of; <code>0<\/code> shows top-level\n\n\n  <code>columns<\/code>\n  <code>3<\/code>\n  grid columns\n\n\n  <code>show_count<\/code>\n  <code>\"1\"<\/code>\n  show the count of downloads per category\n\n\n  <code>show_description<\/code>\n  <code>\"1\"<\/code>\n  show the category description text\n\n\n\n\n<h4>[isoft_fmf_search] \u2014 search box<\/h4>\n\n<p>Renders a search form that filters Foundation downloads.<\/p>\n\n\n\n\n  Attribute\n  Default\n  What\n\n\n\n\n  <code>category<\/code>\n  empty\n  scope the search to a single category (slug or term ID)\n\n\n  <code>placeholder<\/code>\n  \"Search downloads\u2026\"\n  the input placeholder text\n\n\n\n\n<h4>[isoft_fmf_recent] \u2014 latest downloads<\/h4>\n\n<p>Pre-set list, newest first.<\/p>\n\n\n\n\n  Attribute\n  Default\n  What\n\n\n\n\n  <code>limit<\/code>\n  <code>5<\/code>\n  how many to render\n\n\n  <code>days<\/code>\n  <code>0<\/code>\n  restrict to downloads posted in the last N days; <code>0<\/code> = no time limit\n\n\n  <code>category<\/code>\n  empty\n  scope to a single category\n\n\n\n\n<h4>[isoft_fmf_popular] \u2014 most-downloaded<\/h4>\n\n<p>Pre-set list, ordered by download count.<\/p>\n\n\n\n\n  Attribute\n  Default\n  What\n\n\n\n\n  <code>limit<\/code>\n  <code>5<\/code>\n  how many to render\n\n\n  <code>period<\/code>\n  <code>\"all\"<\/code>\n  <code>all<\/code> \/ <code>30d<\/code> \/ <code>7d<\/code>\n\n\n  <code>category<\/code>\n  empty\n  scope to a single category\n\n\n\n\n<h4>[isoft_fmf_button file_id=\"42\"] \u2014 a single download button<\/h4>\n\n<p>Renders just a download button for one specific file (not the whole download post). Useful inline in body content.<\/p>\n\n\n\n\n  Attribute\n  Default\n  What\n\n\n\n\n  <code>file_id<\/code>\n  required\n  the file ID (visible in the per-file list on the download edit screen)\n\n\n  <code>text<\/code>\n  \"Download\"\n  button label\n\n\n  <code>class<\/code>\n  empty\n  extra CSS classes appended to the button\n\n\n\n\n<h4>[isoft_fmf_count] \u2014 download counter<\/h4>\n\n<p>Renders just a number \u2014 either a single file's count or a whole download post's total.<\/p>\n\n\n\n\n  Attribute\n  Default\n  What\n\n\n\n\n  <code>id<\/code>\n  <code>0<\/code>\n  download post ID (uses the post's aggregate counter)\n\n\n  <code>file_id<\/code>\n  <code>0<\/code>\n  specific file ID (uses that file's counter)\n\n\n  <code>format<\/code>\n  <code>\"%s\"<\/code>\n  sprintf format string for the number, e.g. <code>\"%s downloads\"<\/code>\n\n\n\n\n<p>Exactly one of <code>id<\/code> or <code>file_id<\/code> should be set.<\/p>\n\n<h4>Builder widget reference<\/h4>\n\n<p>The shortcodes above drop into every major builder's HTML or Shortcode widget. Where to paste:<\/p>\n\n\n\n\n  Builder\n  Widget\n\n\n\n\n  Elementor\n  Widgets panel \u2192 <strong>Shortcode<\/strong>\n\n\n  WPBakery\n  Add element \u2192 <strong>Text Block<\/strong> (source view) or <strong>Raw HTML<\/strong>\n\n\n  Divi\n  Module \u2192 <strong>Code<\/strong>\n\n\n  Beaver Builder\n  Basic Modules \u2192 <strong>HTML<\/strong>\n\n\n  Bricks\n  Basic Elements \u2192 <strong>Shortcode<\/strong>\n\n\n\n\n<p>Native, point-and-click widgets for each builder (with full attribute panels instead of writing shortcode strings) are planned as separate companion plugins.<\/p>\n\n<h3>Customizing appearance<\/h3>\n\n<p>I-Soft File Manager: Foundation exposes its styling via CSS custom properties on <code>:root<\/code> so you can recolor cards from <strong>Appearance \u2192 Customize \u2192 Additional CSS<\/strong> without writing any selectors.<\/p>\n\n<p>Example \u2014 recolor the PDF icon to match your theme blue and soften card borders:<\/p>\n\n<pre><code>:root {\n    --isoft-fmf-icon-pdf-bg: #1a73e8;\n    --isoft-fmf-card-border: #ddd;\n}\n<\/code><\/pre>\n\n<h4>Available CSS variables<\/h4>\n\n<ul>\n<li><code>--isoft-fmf-card-bg<\/code> \u2014 Card background<\/li>\n<li><code>--isoft-fmf-card-border<\/code> \u2014 Card and grid borders<\/li>\n<li><code>--isoft-fmf-row-border<\/code> \u2014 Per-file row separator<\/li>\n<li><code>--isoft-fmf-title-band-bg<\/code> \u2014 Grid-mode title band background<\/li>\n<li><code>--isoft-fmf-meta-color<\/code> \u2014 Date \/ size \/ count text<\/li>\n<li><code>--isoft-fmf-empty-color<\/code> \u2014 \"No files available\" text<\/li>\n<li><code>--isoft-fmf-badge-hot-bg<\/code> \u2014 HOT badge background<\/li>\n<li><code>--isoft-fmf-badge-hot-color<\/code> \u2014 HOT badge text<\/li>\n<li><code>--isoft-fmf-icon-color<\/code> \u2014 File-type icon\/badge text<\/li>\n<li><code>--isoft-fmf-icon-pdf-bg<\/code> \u2014 PDF file color<\/li>\n<li><code>--isoft-fmf-icon-doc-bg<\/code> \u2014 DOC \/ DOCX color<\/li>\n<li><code>--isoft-fmf-icon-xls-bg<\/code> \u2014 XLS \/ XLSX color<\/li>\n<li><code>--isoft-fmf-icon-ppt-bg<\/code> \u2014 PPT \/ PPTX color<\/li>\n<li><code>--isoft-fmf-icon-zip-bg<\/code> \u2014 Archive (ZIP \/ RAR \/ 7Z) color<\/li>\n<li><code>--isoft-fmf-icon-img-bg<\/code> \u2014 Image color<\/li>\n<li><code>--isoft-fmf-icon-vid-bg<\/code> \u2014 Video color<\/li>\n<li><code>--isoft-fmf-icon-aud-bg<\/code> \u2014 Audio color<\/li>\n<li><code>--isoft-fmf-icon-file-bg<\/code> \u2014 Generic \/ unknown file color<\/li>\n<\/ul>\n\n<h4>Targeting individual classes<\/h4>\n\n<p>For deeper changes (layout, spacing, typography), all public classes use the <code>.isoft-fmf-<\/code> prefix with BEM naming. Key entry points:<\/p>\n\n<ul>\n<li><code>.isoft-fmf-download-card<\/code> \u2014 Outer wrapper around one download<\/li>\n<li><code>.isoft-fmf-download-card__title<\/code> \u2014 Multi-file card heading<\/li>\n<li><code>.isoft-fmf-file-item<\/code> \u2014 Per-file row<\/li>\n<li><code>.isoft-fmf-file-item__icon<\/code> \u2014 Large file-type tile (list mode only)<\/li>\n<li><code>.isoft-fmf-file-item__title<\/code> \u2014 File or download title link<\/li>\n<li><code>.isoft-fmf-file-item__meta<\/code> \u2014 Date \/ size \/ count meta block<\/li>\n<li><code>.isoft-fmf-file-item__action<\/code> \u2014 Action column (button or status label)<\/li>\n<li><code>.isoft-fmf-download-btn<\/code> \u2014 The action button (intentionally not theme-locked via CSS variables; targets WP <code>wp-element-button<\/code> so theme styling stays in control)<\/li>\n<li><code>.isoft-fmf-meta--type<\/code> \u2014 Inline file-type badge (grid mode only)<\/li>\n<li><code>.isoft-fmf-badge--hot<\/code> \u2014 HOT marker<\/li>\n<li><code>.isoft-fmf-grid<\/code> \u2014 Grid wrapper (use <code>.isoft-fmf-grid--cols-3<\/code> etc. for per-column-count overrides)<\/li>\n<li><code>.isoft-fmf-list-wrap<\/code> \u2014 List wrapper<\/li>\n<li><code>.isoft-fmf-category-grid<\/code> \u2014 Category grid wrapper<\/li>\n<\/ul>\n\n<h3>Source code<\/h3>\n\n<p>Full source \u2014 including the un-minified React\/JSX for the three Gutenberg blocks \u2014 is hosted publicly at:<\/p>\n\n<p>https:\/\/github.com\/I-SOFT-Mionica\/isoft-fm-foundation<\/p>\n\n<p>The compiled block bundles shipped under <code>blocks\/build\/<\/code> are produced from <code>blocks\/&lt;block-name&gt;\/{index,edit}.js<\/code> via <code>@wordpress\/scripts<\/code> (webpack). To rebuild from a clean checkout:<\/p>\n\n<pre><code>npm install\nnpm run build\n<\/code><\/pre>\n\n<p>The build script reads <code>webpack.config.js<\/code>, compiles each block's <code>index.js<\/code> entry, and writes <code>blocks\/build\/&lt;block-name&gt;.js<\/code> plus an <code>&lt;block-name&gt;.asset.php<\/code> dependency manifest. Running <code>npm run start<\/code> instead watches the sources and rebuilds on save during development.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>isoft-fm-foundation<\/code> folder to <code>\/wp-content\/plugins\/<\/code>, or install via <strong>Plugins \u2192 Add New \u2192 Upload Plugin<\/strong>.<\/li>\n<li>Activate through the <strong>Plugins<\/strong> menu.<\/li>\n<li>Visit <strong>I-Soft File Manager: Foundation \u2192 Settings<\/strong> to configure storage, access roles, PDF thumbnails, and log retention.<\/li>\n<li>Create at least one <strong>Download Category<\/strong> \u2014 this is required before any file can be uploaded. Categories map directly to folder names under <code>wp-content\/uploads\/isoft-fmf-files\/<\/code>.<\/li>\n<li>To restrict an editor to specific folders, edit their user profile (<strong>Users \u2192 Edit User<\/strong>) and check the allowed categories under <strong>I-Soft File Manager: Foundation \u2014 Allowed Categories<\/strong>. Leave empty for no access. Administrators are always unrestricted.<\/li>\n<\/ol>\n\n<h4>Server requirements<\/h4>\n\n<ul>\n<li>PHP 8.4 or higher<\/li>\n<li>WordPress 6.7 or higher<\/li>\n<li>MySQL 5.7+ or MariaDB 10.3+<\/li>\n<li>Apache with <code>mod_rewrite<\/code> + <code>mod_authz_core<\/code>, or Nginx<\/li>\n<li>Database user with <code>CREATE<\/code>, <code>ALTER<\/code>, <code>INDEX<\/code>, <code>REFERENCES<\/code>, and <code>DROP<\/code> on the WordPress database (needed once on activation to create the plugin's tables; common on locked-down shared hosts to be missing)<\/li>\n<li>Imagick PHP extension for PDF thumbnails<\/li>\n<\/ul>\n\n<!--section=faq-->\n<dl>\n<dt id=\"why%20not%20just%20use%20the%20default%20wordpress%20media%20library%3F\"><h3>Why not just use the default WordPress Media Library?<\/h3><\/dt>\n<dd><p>The Media Library flattens everything into <code>wp-content\/uploads\/YYYY\/MM\/<\/code>, which breaks predictable automation and makes category-based permissions impossible. Foundation keeps files organized by category \u2014 which is what large organizations actually need when managing thousands of documents.<\/p><\/dd>\n<dt id=\"how%20does%20the%20category-as-folder%20architecture%20work%3F\"><h3>How does the Category-as-Folder architecture work?<\/h3><\/dt>\n<dd><p>Foundation stores files outside the Media Library in a predictable per-category folder tree (<code>wp-content\/uploads\/isoft-fmf-files\/<\/code>). The filesystem is the source of truth. Moving a download to a different category auto-moves its files on disk. This lets external automation tools (Rclone, SFTP, scheduled scans) sync files in and out without having to understand WordPress internals.<\/p><\/dd>\n<dt id=\"can%20i%20assign%20a%20download%20to%20multiple%20categories%3F\"><h3>Can I assign a download to multiple categories?<\/h3><\/dt>\n<dd><p>No \u2014 each download lives in exactly one category. Categories are physical folders on your server, and a file can only sit in one folder at a time (just like on your computer). If you need a document to appear under several groupings, use tags instead \u2014 those are intentionally many-to-many and don't affect storage. <strong>Heads up on 0.11.0:<\/strong> WordPress's standard category picker still shows checkboxes that let you pick multiple, but only the first one is actually honored. A patch coming right after this release replaces that picker with a proper single-select dropdown so the UI matches the underlying rule.<\/p><\/dd>\n<dt id=\"can%20i%20migrate%20from%20jdownloads%3F\"><h3>Can I migrate from jDownloads?<\/h3><\/dt>\n<dd><p>Yes \u2014 but via a separate companion plugin, <strong>I-Soft File Manager: Arbiter<\/strong> (coming soon). Foundation's data model is intentionally close to jDownloads to make a one-shot import practical; Arbiter reads the legacy tables directly and rebuilds the category tree, downloads, files, and counters into Foundation, preserving slug paths so existing URLs keep working.<\/p><\/dd>\n<dt id=\"how%20do%20i%20restrict%20a%20user%20to%20only%20some%20categories%3F\"><h3>How do I restrict a user to only some categories?<\/h3><\/dt>\n<dd><p>Open their user profile (<strong>Users \u2192 Edit User<\/strong>), scroll to <strong>I-Soft File Manager: Foundation \u2014 Allowed Categories<\/strong>, and check the boxes. Users inherit access to every descendant of a checked category. Administrators bypass all access checks.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20downloads%20if%20i%20delete%20a%20category%3F\"><h3>What happens to downloads if I delete a category?<\/h3><\/dt>\n<dd><p>Deletion is blocked if any download is still assigned to that category \u2014 the files would otherwise be orphaned. Reassign or delete the downloads first, then delete the category.<\/p><\/dd>\n<dt id=\"what%20file%20types%20are%20allowed%3F\"><h3>What file types are allowed?<\/h3><\/dt>\n<dd><p>Configured under <strong>Settings \u2192 General \u2192 Allowed File Extensions<\/strong>. The default list covers common document, archive, image, audio, and video formats. Executables (<code>.exe<\/code>, <code>.sh<\/code>, <code>.bat<\/code>) are not in the default list and should only be added if you know what you're doing.<\/p><\/dd>\n<dt id=\"does%20it%20support%20cyrillic%20or%20other%20non-latin%20filenames%3F\"><h3>Does it support Cyrillic or other non-Latin filenames?<\/h3><\/dt>\n<dd><p>Yes. Uploaded filenames and category slugs are automatically transliterated from Serbian Cyrillic to Latin for disk storage. Display titles keep the original characters. A setting under <strong>Settings \u2192 General \u2192 Cyrillic Titles<\/strong> can auto-fill download titles in Cyrillic from uploaded Latin filenames.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20full%20site%20editing%20%28block%29%20themes%3F\"><h3>Does it work with Full Site Editing (block) themes?<\/h3><\/dt>\n<dd><p>Yes. The plugin detects FSE themes and injects the download card via the <code>the_content<\/code> filter. Classic theme templates under <code>templates\/<\/code> are used as a fallback.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20elementor%2C%20wpbakery%2C%20divi%2C%20beaver%20builder%2C%20or%20bricks%3F\"><h3>Does it work with Elementor, WPBakery, Divi, Beaver Builder, or Bricks?<\/h3><\/dt>\n<dd><p>Yes. Foundation ships eight shortcodes that drop into every major builder's HTML or Shortcode widget. See the <a href=\"#shortcodes\">full shortcode reference<\/a> below for attributes; the <a href=\"#shortcodes\">builder widget table<\/a> at the end of that section shows which widget to paste into in each builder. Native, point-and-click widgets for each builder are planned as separate companion plugins.<\/p><\/dd>\n<dt id=\"the%20plugin%20installed%20but%20every%20upload%20fails%20with%20%22could%20not%20save%20file%20record.%22%20what%27s%20wrong%3F\"><h3>The plugin installed but every upload fails with \"Could not save file record.\" What's wrong?<\/h3><\/dt>\n<dd><p>Your WordPress database user almost certainly lacks the <code>CREATE<\/code> privilege, so the plugin's tables never got created on activation. As of 0.10.19 every admin page shows the exact MySQL error plus a ready-to-paste <code>GRANT<\/code> statement to fix it; visit any plugin admin page to see the notice. On many cPanel hosts you'll need to also re-add the user to the database via cPanel after granting in SQL \u2014 the literal-vs-wildcard underscore escaping bites here.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.11.0<\/h4>\n\n<ul>\n<li><strong>New: category-level default license with file inheritance.<\/strong> Each category now has a \"Default License\" dropdown on its Add\/Edit screen. Downloads in a category that have their License field set to \"\u2014 Inherit from category \u2014\" pick up the category's default automatically. Per-file overrides still win. Set Public Domain on your \"Budget\" and \"Assembly decisions\" categories, set CC BY-SA 4.0 on your \"PR archive\" \u2014 every file in each category inherits the right license without per-file fiddling.<\/li>\n<li><strong>New: two more seeded licenses out of the box.<\/strong> Public Domain \u2014 Serbian Law (Art. 6 \u0417\u0410\u0421\u041f) for official municipal acts that are public domain by operation of law (different mechanism than CC0's author-release PD). Creative Commons BY-SA 4.0 with the standard summary and URL. Both ship alongside the existing four defaults.<\/li>\n<li><strong>New: \"Restore seeded licenses\" button<\/strong> on Downloads \u2192 Licenses. Adds any default licenses missing from your install. Add-only \u2014 existing licenses with the same slug are never overwritten. Use this after a plugin update that ships new default licenses to pull them in with one click.<\/li>\n<li><strong>New: download log now records which license governed each download.<\/strong> A new column on the download log preserves the legal trail. Even if you change a file's license later, you can still answer \"what license was on this file when User X downloaded it on date Y?\" \u2014 important for Creative Commons compliance (CC licenses are irrevocable for already-distributed copies).<\/li>\n<li><strong>New: license chip on download cards.<\/strong> When a download has a license set (or inherits one from its category), the title now appears as a chip in the meta row. If the license has a URL, the chip links out to the canonical source (creativecommons.org, etc.).<\/li>\n<li><strong>Improved: lock icon on download cards now shows the required role<\/strong> (\"Subscriber+\", \"Editor+\", etc.) next to the icon, so visitors know what login level they'd need.<\/li>\n<li><strong>Improved: license change warning.<\/strong> When you change a file's license in the editor, a warning appears if anyone has already downloaded that file. Reminds you that Creative Commons and most permissive licenses are irrevocable for already-distributed copies \u2014 the change only affects new downloads.<\/li>\n<li><strong>Heads up \u2014 known issue with a quick fix on the way.<\/strong> WordPress's standard category picker on the post edit screen still lets you check multiple categories, but Foundation stores every file in exactly one folder on disk (categories are physical folders, not labels) \u2014 only the first checked category actually drives where the file lives. For now, please assign each download to a single category. The next patch swaps the picker for a proper single-select dropdown so this can't happen by accident.<\/li>\n<\/ul>\n\n<h4>0.10.21<\/h4>\n\n<ul>\n<li><strong>Fixed: download cards no longer show a lock icon on publicly accessible files.<\/strong> Files set to \"Inherit from category\" whose categories had no access role configured were cascading correctly to the site-wide default (Public) \u2014 but the card was reading the literal \"inherit\" value when deciding whether to show the lock, so visitors saw a lock chip on files they could actually download without logging in. The card now reads the cascade-resolved role and only shows the lock when the visitor really does need to authenticate.<\/li>\n<\/ul>\n\n<h4>0.10.20<\/h4>\n\n<ul>\n<li><strong>HOT badge and Top Downloads panel now work on new and quiet sites.<\/strong> The HOT recalculation was looking at the last 7 days only \u2014 fine for busy sites but it left brand-new installs and low-traffic sites with an empty Top Downloads panel forever, because there simply wasn't enough recent data. The cron now tries 7 days first, widens to 30 if that's empty, and last-resort falls back to all-time download counts. The Top Downloads dashboard panel labels itself honestly so you can see when it's showing all-time vs recent data.<\/li>\n<li><strong>Fixed: the Top Downloads (Last 30 Days) panel was silently showing 8 days at most<\/strong>, because the daily aggregate table was being purged too aggressively. The retention is now 32 days, so the panel and the 30-day chart actually show 30 days of data.<\/li>\n<\/ul>\n\n<h4>0.10.19<\/h4>\n\n<ul>\n<li><strong>Database setup failures are now visible.<\/strong> When the plugin can't create its required tables (usually because the WordPress database user lacks <code>CREATE<\/code> privilege \u2014 common on locked-down shared hosts), every admin page now shows a clear warning with the exact MySQL error and a ready-to-paste <code>GRANT<\/code> statement to fix it. Previously the install appeared to succeed but every upload silently failed with \"Could not save file record\" and the admin had no clue why.<\/li>\n<li><strong>More helpful upload and save errors.<\/strong> Failed file uploads now report the specific reason (file too large, server out of temp space, security plugin blocked it, etc.) instead of a generic \"upload error.\" Failed database saves include the underlying MySQL error so you can see whether a column is missing, the disk is full, or something else.<\/li>\n<\/ul>\n\n<h4>0.10.18<\/h4>\n\n<ul>\n<li><strong>New: External Link Target setting<\/strong> under Settings \u2192 Display. Choose whether external-URL download buttons (Google Drive, Dropbox, etc.) open in a new tab or the same window. Defaults to new tab \u2014 the modern web convention and what visitors usually expect for off-site links. Local-file downloads are unaffected.<\/li>\n<li><strong>Fixed: downloads failed to start on Nginx and similar hosts<\/strong> where auto-mode picked a serve method the server couldn't actually fulfill. Auto-mode now safely streams via PHP; admins who have X-Sendfile or X-Accel-Redirect properly configured can opt in via Settings \u2192 Security \u2192 File Serving Method.<\/li>\n<li><strong>Fixed: PHP-streamed downloads hung<\/strong> on hosts with output gzip, nested output buffers, or aggressive FastCGI buffering. The stream now drains every level of output buffering, disables on-the-fly compression, and pushes data in 8 KB chunks so the file starts arriving immediately instead of waiting for the whole response to assemble.<\/li>\n<li><strong>Fixed: Cyrillic-titled downloads kept the locale's auto-draft slug<\/strong> (for example <code>automatski-nacrt<\/code> under Serbian Latin, <code>auto-draft<\/code> under English) instead of transliterating the title. User-customized slugs are still preserved as before.<\/li>\n<li><strong>Fixed: download links silently failed on themes using AJAX page navigation<\/strong> (djax, pjax, swup, hotwire-turbo, instantclick). Those libraries intercept every link click and try to swap the response into the page as HTML \u2014 which explodes when the response is a binary file. Download buttons now ship with the HTML5 <code>download<\/code> attribute and the plugin's own click handler runs first so the theme can't hijack the request.<\/li>\n<\/ul>\n\n<h4>0.10.17<\/h4>\n\n<ul>\n<li><strong>Smart ZIP bundle cache expiry.<\/strong> Bundle cache now expires on <em>idle time<\/em> (last access), not build age \u2014 so a bundle being downloaded daily no longer gets rebuilt on a schedule. A hard ceiling at 3\u00d7 the configured duration guarantees an eventual refresh regardless.<\/li>\n<\/ul>\n\n<h4>0.10.13 \u2014 0.10.16<\/h4>\n\n<ul>\n<li><strong>Faster statistics dashboard.<\/strong> Now reads from a daily aggregate table instead of scanning the full per-event log; refreshes immediately on every download instead of after a 5-minute cache.<\/li>\n<li><strong>ZIP bundle self-cleanup.<\/strong> A daily sweep removes stale or orphaned bundles from disk; deleting a download immediately clears its cache. A \"Clear bundle cache now\" button covers manual cleanup.<\/li>\n<li><strong>Broken-link recovery on Windows hosts.<\/strong> Renamed or moved files are now relinked via SHA-256 content matching, not just POSIX inode (Linux\/POSIX still uses the faster inode path).<\/li>\n<li><strong>Manual \"Run integrity check now\" button<\/strong> on the Broken Links screen, with overlap protection and auto-recovery if the scan crashes mid-flight.<\/li>\n<li><strong>Realistic demo content<\/strong> that models a real document lifecycle (release-day spike, decay, weekend dampening) so first-impression screenshots look like a live site.<\/li>\n<\/ul>\n\n<h4>0.10.0 \u2014 0.10.12<\/h4>\n\n<ul>\n<li><strong>Category-level access roles.<\/strong> Categories can declare their own minimum role (Public, Subscriber+, Editor+, etc.). Downloads can be set to inherit the strictest permission across their assigned categories.<\/li>\n<li><strong>One-click ZIP bundles<\/strong> for multi-file downloads. Visitors can grab everything as a single archive; optional on-disk cache via Settings \u2192 Display.<\/li>\n<li><strong>Multi-file summary tiles.<\/strong> In listings, multi-file downloads now render as a single summary card (file count, distinct types, total size, single \"Download all\" button) instead of one row per file.<\/li>\n<li><strong>User-agent blocklist<\/strong> under Settings \u2192 Security for blocking specific scrapers or bots.<\/li>\n<li><strong>Featured-first listings.<\/strong> Downloads marked Featured pin to the top of any list regardless of sort order.<\/li>\n<li><strong>External-only flag<\/strong> for downloads where the external URL is canonical and the local file is just a backup.<\/li>\n<li>Plus a bundle of fixes for the Category Grid block and a settings-tab regression where saving one tab wiped checkboxes on the others.<\/li>\n<\/ul>\n\n<h4>0.8.0 \u2014 0.9.1<\/h4>\n\n<ul>\n<li><strong>WordPress.org review preparation.<\/strong> Full Coding Standards compliance pass, escape and nonce audits, REST capability hardening, and the official rename to <strong>I-Soft File Manager: Foundation<\/strong> (slug <code>isoft-fm-foundation<\/code>).<\/li>\n<\/ul>\n\n<h4>0.7.0 \u2014 0.7.2<\/h4>\n\n<ul>\n<li><strong>Themeable via CSS custom properties.<\/strong> Every color in the public stylesheet is exposed as a <code>--isoft-fmf-*<\/code> variable on <code>:root<\/code> \u2014 recolor anything by overriding a single variable in Customizer \u2192 Additional CSS.<\/li>\n<li><strong>Demo content creates a showcase page<\/strong> automatically so new users can see all three embed patterns side-by-side.<\/li>\n<\/ul>\n\n<h4>0.5.0 \u2014 0.6.1<\/h4>\n\n<ul>\n<li><strong>Rate limiting and hotlink protection<\/strong> fully enforced (configurable per IP\/hour, configurable referer check).<\/li>\n<li><strong>Lighter PDF thumbnail backend<\/strong> \u2014 Imagick-only; removed every <code>exec()<\/code> call from the codebase.<\/li>\n<\/ul>\n\n<h4>0.4.0 \u2014 0.4.9<\/h4>\n\n<ul>\n<li><strong>Broken-link recovery.<\/strong> Daily scheduled scan detects missing files. Visitors hitting a missing file see a friendly \"temporarily unavailable\" page instead of an error.<\/li>\n<li><strong>Object cache layer<\/strong> for hot-path reads, and the <strong>Broken Links admin screen<\/strong> with per-row recovery options (Move back, Reassign, Split, Reupload, Detach).<\/li>\n<li><strong>Container-query grid<\/strong> that adapts to any sidebar or column width.<\/li>\n<\/ul>\n\n<h4>0.3.0 \u2014 0.3.9<\/h4>\n\n<ul>\n<li><strong>Per-user category access control<\/strong> with subtree inheritance.<\/li>\n<li><strong>Grid view redesign<\/strong> with colored file-type badges and clean layout bands.<\/li>\n<\/ul>\n\n<h4>0.2.1 \u2014 0.2.9<\/h4>\n\n<ul>\n<li><strong>Category-as-folder architecture introduced.<\/strong> Creating a category creates a real physical folder on the server.<\/li>\n<li><strong>From Folder browser<\/strong> for files dropped in via external tools.<\/li>\n<li><strong>Cyrillic-to-Latin transliteration<\/strong> for safe filesystem storage.<\/li>\n<li><strong>Inline metadata editing<\/strong> directly from the file list.<\/li>\n<\/ul>","raw_excerpt":"Document and download manager with real on-disk folder organization, per-department access control, and multi-file downloads.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/303026","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=303026"}],"author":[{"embeddable":true,"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/chillic"}],"wp:attachment":[{"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=303026"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=303026"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=303026"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=303026"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=303026"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/ast.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=303026"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}