Yii2: possible problem in Assets docs or beforeCopy option?

Created on 16 Feb 2015  路  9Comments  路  Source: yiisoft/yii2

so I tried following tip from official docs to only publish desired folders in assets directory:

    public function init()
    {
        parent::init();
        $this->publishOptions['beforeCopy'] = function ($from, $to) {
            $dirname = basename(dirname($from));
            return $dirname === 'fonts' || $dirname === 'css';
        };
    }

I'm also publishing font-awesome package, just like example above. but using this, not a single file publishes to the assets folder, only an empty folder got created in there.
I checked and the problem is that $dirname variable always has the value of components-font-awesome which is the name of package's main folder. It seems that $from parameter passed to the function only loops through first-level content in main category, while above code assumes it goes inside folders and has the name of every file within package. here is what var_dumping $from parameter shows me:

public function init()
    {
        parent::init();
        $this->publishOptions['beforeCopy'] = function ($from, $to) {
            var_dump($from);
            $dirname = basename(dirname($from));
            return $dirname === 'fonts' || $dirname === 'css';
        };
    }

string(80) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/.gitignore"
string(80) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/bower.json"
string(73) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/css"
string(75) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/fonts"
string(74) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/less"
string(79) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/README.md"
string(74) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/scss"

I just made a little change trying to solve the problem, but the value of $from parameter changes if I make following change!! :

public function init()
    {
        parent::init();
        $this->publishOptions['beforeCopy'] = function ($from, $to) {
            var_dump($from);
            //$dirname = basename(dirname($from));
            $dirname = basename($from);
            return $dirname === 'fonts' || $dirname === 'css';
        };
    }

string(80) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/.gitignore"
string(80) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/bower.json"
string(73) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/css"
string(83) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/css/.DS_Store"
string(90) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/css/font-awesome.css"
string(94) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/css/font-awesome.min.css"
string(75) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/fonts"
string(85) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/fonts/.DS_Store"
string(99) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/fonts/fontawesome-webfont.eot"
string(99) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/fonts/fontawesome-webfont.svg"
string(99) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/fonts/fontawesome-webfont.ttf"
string(100) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/fonts/fontawesome-webfont.woff"
string(101) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/fonts/fontawesome-webfont.woff2"
string(91) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/fonts/FontAwesome.otf"
string(74) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/less"
string(79) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/README.md"
string(74) "/Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/scss"

now it includes all the files in package! what is wrong here? it changes behaviour and I don't get why!

docs

All 9 comments

Are you sure you didn't change anything else? Like your assetManager config? The $from value should go through all the files as it does in your last example, regardless of the code changes you have listed here. If all the files listed in your last example are iterated over, then $dirname = basename(dirname($from)); should work, because it gets the basename of the directory which the current file is in, e.g. in the case of /Applications/MAMP/htdocs/portal/vendor/bower/components-font-awesome/css/font-awesome.css, $dirname will be css, and return true for the function.

Thanks for reply @spikyjt
I just downloaded a new basic app template and test the whole process on that, and same results happened. so my other changes are not the cause of error.
I asked my colleague to test it on his environment and the same error occurred there. it would be great if someone within the core team check this and correct the docs. it seems to be wrong.

Actually it looks like a duplicate of #6487
Well done for thorough testing!

Oh I haven't seen that before. thanks for pointing it out :+1:
One last thing though, It seems this is how beforeCopy callback works:
It iterates through each file/folder directly within parent directory first, foreach file/folder, if the function returns true, it publishes it and then attempts to iterate through files within that _ of course if it's a folder _ and the same goes for each file/folder in that directory. It's a recursive process.
In my above code, in second case it only iterated through files within fonts and css folders. and it just published two empty folders named fonts and css in assets folder, because those are the only cases for which beforeCopy returned true.
considering that, this is how I solved my problem:

    public function init()
    {
        parent::init();
        $this->publishOptions['beforeCopy'] = function ($from, $to) {
            $publish = false;
            $dirname = basename($from);
            $parentFolder = basename(dirname($from));
            if (
                ($dirname === 'fonts' || $dirname === 'css') or
                ($parentFolder === 'fonts' || $parentFolder === 'css')
                ) {
                $publish = true;
            }
            return $publish;
        };
    }

I leave finding the best solution and updating docs to core team, I'm not sure if there is a better way or not.

@hesna I faced the same problem. your way saved me. thanks a lot bro.
just waiting for core team's response for better way if any available.

Issue resolved by commit 8a506e1

I suppose must be:

'only' => [
            'fonts/*',
            'css/*',
        ]

not:

'only' => [
            'fonts/',
            'css/',
        ]

Because I have empty directories.

should work with both...

Only this works for me.

'only' => [
    'fonts/*',
    'css/*',
]
Was this page helpful?
0 / 5 - 0 ratings