Make any model attribute blade compilable

Submitted by nohalfpixels - 8 years ago

This trait allows you to save any column from any model into a location within the storage directory to allow the column to be blade compilable with view()->file($model->getViewableColumnPath('column_name')); The trait

<?php

use Illuminate\Support\Facades\File;
use Symfony\Component\Finder\Finder;

trait ViewableColumns {

    //this can be overwritten in any model that uses the trait
    //protected $viewableExtension = '.blade.php';
    
    public static function bootViewableColumns(){
        static::deleted( function ($model) {
            $model->deleteViewableColumns();
        });
    }

    private function getViewableExtension(){
        return isset($this->viewableExtension) ? $this->viewableExtension : '.blade.php';
    }

    private function getViewableFileId($column){
        return $this->getKey() . '_' . $column . $this->getViewableExtension();
    }

    private function getViewableDirectory(){
        return storage_path('app/viewable/' . preg_replace("/[^a-zA-Z0-9\_]+/", '', snake_case(static::class)));
    }

    private function getViewablePath($column){
        return $this->getViewableDirectory() . '/' . $this->getViewableFileId($column);
    }

    private function maybeUpdateFile($column){
        //if model folder doesnt exist create it
        if(!File::isDirectory($this->getViewableDirectory())){
            File::makeDirectory($this->getViewableDirectory(), 777, true);
        }
        //if file exists but is older than last updated or if file doesnt exist put contents
        if(!File::exists($this->getViewablePath($column)) || File::exists($this->getViewablePath($column)) && $this->updated_at->timestamp > File::lastModified($this->getViewablePath($column)) || $this->isDirty($column) )
        {
            File::put($this->getViewablePath($column), $this->{$column});
        }
    }

    public function getViewableColumnPath($column){
        $this->maybeUpdateFile($column);
        return $this->getViewablePath($column);
    }

    public function deleteViewableColumns(){
        $files = Finder::create()->files()->in($this->getViewableDirectory() . '/')->name($this->getKey().'_*');
        foreach($files as $file){
            File::delete($file->getRealPath());
        }
        $remainingFiles = Finder::create()->files()->in($this->getViewableDirectory() . '/')->exclude('.*')->count();
        if($remainingFiles == 0){
            File::deleteDirectory($this->getViewableDirectory());
        }
    }
}



// Usage within route/controller method, you can use ANY data, functions etc on the view instance as you would normally, and all ::extends() for blade and view will also be applied
return view()->file($model->getViewableColumnPath('column_name'))->with().......;