Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generator for an index of file downloads #444

Open
brooksvb opened this issue Feb 12, 2020 · 3 comments
Open

Generator for an index of file downloads #444

brooksvb opened this issue Feb 12, 2020 · 3 comments

Comments

@brooksvb
Copy link

I want to have a directory that contains files for users to download on the website.

files/pdfs/
  - file1.pdf
  - file2.pdf
  - file3.pdf

Webpage:

Download files

I figured that in order to accomplish this, I will need to extend Sculpin and write a custom generator. I've really struggled in figuring out where to even start in order to tie into the site generation since the documentation is so vague and lacking.

So far I have created and registered a bundle which includes an event subscriber:

<?php
// app/SculpinFileGeneratorBundle/FileGenerator.php

use Sculpin\Core\Event\SourceSetEvent;
use Sculpin\Core\Sculpin;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class FileGenerator implements EventSubscriberInterface
{

	/**
	 * @inheritDoc
	 */
	public static function getSubscribedEvents()
	{
		return [
			Sculpin::EVENT_BEFORE_RUN => 'beforeRun'
		];
	}

	public function beforeRun(SourceSetEvent $sourceSetEvent)
	{

	}
}

I was only able to get this far by trying to poke around some other repos that use Sculpin. Now I've been reading through and trying to reverse-engineer this SourceSetEvent to figure out what to do with it, and I'm getting lost.

As I understand currently, I need to use a generator to generate a list of the files I want to index and their filenames. Then in a template, I can use that generator as a data source,

---
generator: file_generator
---

and then render a link to each one. I have no idea how to do everything in-between.

I really wanted to use Sculpin because it seemed simple, it uses PHP, and it supports Twig out of the box, but the lack of documentation has been extremely disappointing.

Any advice or guidance would be appreciated.

@beryllium
Copy link
Member

A few questions:

  1. Are you certain it needs to be a generator? From what I recall, these are generally intended to be used when assembling meta-lists, i.e., for pagination or taxonomies, and the data source is fed into them.

  2. How many folders of files are you planning to have? Just one for PDFs, or multiple? Will it be a nested file structure?

One approach for the suggested use case (a list of PDFs) might be creating a Twig function that can list the files in a folder, so you can iterate them in Twig to generate the listing HTML.

@beryllium
Copy link
Member

So here's what I've come up with using a Twig function:

Append to app/config/sculpin_kernel.yml:

services:
  beryllium.file_lister:
    class: FileListerTwigExtension
    arguments:
      $sourceDir: '%sculpin.source_dir%'
    tags:
      - 'twig.extension'
    public: true

Create app/FileListerTwigExtension.php:

<?php

class FileListerTwigExtension extends Twig\Extension\AbstractExtension {
    protected $sourceDir;

    public function __construct($sourceDir) {
        $this->sourceDir = rtrim($sourceDir, DIRECTORY_SEPARATOR);
    }

    public function getFunctions() {
        return [
            new Twig\TwigFunction(
                'list_folder_contents',
                [$this, 'listFolderContents']
            )
        ];
    }

    public function listFolderContents($dir) {
        $files = glob($this->sourceDir . DIRECTORY_SEPARATOR . $dir . "/*");

        foreach ($files as $key => $file) {
            $files[$key] = str_replace($this->sourceDir, '', $file);
        }

        return $files;
    }
}

Add to the top of app/SculpinKernel.php (above the class defintion):

require __DIR__ . "/FileListerTwigExtension.php";

And finally, add this to the page you want to list the files on:

<h2>Files:</h2>
<ul>
{% for i in list_folder_contents('files') %}
<li>{{i}}</li>
{% endfor %}
</ul>

This will output a listing of all files in the source/files/ folder.

It's quite complicated, which is unfortunate. I looked into Jigsaw (a laravel-based static site generator) and didn't see anything that jumped out as solving this problem in a built-in way. I don't have much experience with the other major static site generators (jekyll, hugo, gatsby), though, so I'm not sure if they'd be less finicky about this.

I hope this helps.

@brooksvb
Copy link
Author

I'm not super clear on the terminology used in Sculpin between generators and types and whatever. I thought that a generator would be a way to process and provide data to the template.

I can do the work to process the files and create some kind of data structure to be used in rendering, my issue was just figuring out how to get my logic tied into the Sculpin lifecycle.

It looks like your Twig extension method might work for me. I will try this out.

Thanks for your time and help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants