booted) { return; } $this->booted = true; add_filter('upload_mimes', [$this, 'allow_model_mimes'], 99); add_filter('wp_check_filetype_and_ext', [$this, 'validate_model_filetype'], 99, 5); if (is_multisite()) { add_filter('site_option_upload_filetypes', [$this, 'allow_multisite_model_extensions'], 99); } $this->providers = new MaterialProviderRegistry(); $this->providers->register( new InternalMaterialProvider(), __('Internal material library', '3d-print-showcase'), __('Create and manage materials directly in 3D Print Showcase.', '3d-print-showcase') ); $this->providers->register( new RemoteRestMaterialProvider(), __('Denis3D REST API', '3d-print-showcase'), __('Load filament materials directly from the built-in Denis3D WordPress REST API source. All pages are loaded automatically.', '3d-print-showcase'), '', 'remote_rest' ); $customRestUrl = trim((string) Settings::get('custom_rest_url', '')); if ($customRestUrl !== '') { $this->providers->register( new RemoteRestMaterialProvider('custom_rest', $customRestUrl, 'ds82_3dps_custom_rest_status'), __('Custom REST / JSON URL', '3d-print-showcase'), __('Load filament materials from your own compatible WordPress REST / JSON endpoint.', '3d-print-showcase'), '', 'custom_rest' ); } else { $this->providers->register( new RemoteRestMaterialProvider('custom_rest', RemoteRestMaterialProvider::DENIS3D_ENDPOINT, 'ds82_3dps_custom_rest_status'), __('Custom REST / JSON URL', '3d-print-showcase'), __('Enter your own compatible REST / JSON URL below, save the settings, then select this source.', '3d-print-showcase'), '', 'custom_rest' ); } do_action('ds82_3dps_register_material_providers', $this->providers); $overrides = new MaterialOverrideStore(); $this->materials = new MaterialRepository($this->providers, $overrides); $this->integrations = new IntegrationRegistry(); do_action('ds82_3dps_register_integrations', $this->integrations, $this->materials, $this->providers); (new AdminPages($this->materials, $this->providers, $this->integrations, $overrides))->register(); (new RestController($this->materials))->register(); (new ShortcodeViewer($this->materials))->register(); $this->integrations->boot(); do_action('ds82_3dps_loaded', $this); } public function materials(): ?MaterialRepository { return $this->materials; } public function providers(): ?MaterialProviderRegistry { return $this->providers; } public function integrations(): ?IntegrationRegistry { return $this->integrations; } public function allow_model_mimes(array $mimes): array { foreach ($this->supported_model_types() as $extension => $mime) { $mimes[$extension] = $mime; } return $mimes; } public function allow_multisite_model_extensions(mixed $filetypes): string { $current = is_string($filetypes) ? preg_split('/\s+/', trim($filetypes)) : []; $current = is_array($current) ? array_filter($current) : []; foreach (array_keys($this->supported_model_types()) as $extension) { if (!in_array($extension, $current, true)) { $current[] = $extension; } } return implode(' ', array_values(array_unique($current))); } public function validate_model_filetype(mixed $data, mixed $file, mixed $filename, mixed $mimes, mixed $realMime = null): array { if (!is_array($data)) { $data = ['ext' => false, 'type' => false, 'proper_filename' => false]; } $extension = strtolower((string) pathinfo(is_string($filename) ? $filename : '', PATHINFO_EXTENSION)); $types = $this->supported_model_types(); if ($extension === '' || !isset($types[$extension])) { return $data; } if (empty($data['ext']) || empty($data['type'])) { $data['ext'] = $extension; $data['type'] = $types[$extension]; $data['proper_filename'] = null; } return $data; } private function supported_model_types(): array { return [ 'stl' => 'model/stl', '3mf' => 'model/3mf', 'glb' => 'model/gltf-binary', 'gltf' => 'model/gltf+json', ]; } }