0

I am trying to provide video transcripts for each product video in a magento 2 site. I want to pull the transcript from the "video description" field in the admin area, and I have been somewhat successful, but only for a single video. Here is my code:

Transcript.php

<?php
namespace MyNamespace\VideoTranscript\Block;

use Magento\Framework\App\ResourceConnection;
use Magento\Framework\View\Element\Template\Context;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\View\Element\Template;

class Transcript extends Template
{
    protected $resource;
    protected $product;
    protected $storeManager;
    protected $registry;

    public function __construct(
        Context $context,
        $data = [],
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Registry $registry,
        ResourceConnection $resource
    ) {
        parent::__construct($context, $data);
        $this->resource = $resource;
        $this->storeManager = $storeManager;
        $this->registry = $registry;
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $this->product = $objectManager->get('Magento\Framework\Registry')->registry('current_product');
    }

    public function getVideoDescription()
    {
        $connection = $this->resource->getConnection();
        $tableName = $this->resource->getTableName('catalog_product_entity_media_gallery_value_video');
        $storeId = $this->storeManager->getStore()->getId();
        $productId = $this->product->getId();
        $select = $connection->select()
            ->from($tableName, ['description'])
            ->joinLeft('catalog_product_entity_media_gallery_value_to_entity', 'catalog_product_entity_media_gallery_value_video.value_id = catalog_product_entity_media_gallery_value_to_entity.value_id')
            ->where('catalog_product_entity_media_gallery_value_to_entity.entity_id = ?', $productId)
            ->limit(1);

        $description = $connection->fetchOne($select);
        return $description;
    }
}

video_description.phtml

<?php if ($block->getVideoDescription()): ?>

<script type="text/javascript">
function createTranscript() {
    const transcript = document.createElement('article');
    transcript.innerHTML = `
        <a style="margin: 0.5em; text-decoration: none;" class="video-description__toggle button btn btn-warning">Show Transcript</a>
        <p style="display: none;"><?php echo($block->getVideoDescription()); ?></p>
    `;
    jQuery('.product.media').append(transcript);
    jQuery('.video-description__toggle').click(function() {
        jQuery(this).next().slideToggle();
    });
    console.log('Transcript generated')
}

require(["jquery"], function ($) {
    jQuery(document).ready(function() {
        setTimeout(() => {
            createTranscript();
        }, 3500);
    });
});
</script>

<?php endif; ?>

I realize that the "limit 1" argument in my query in getVideoDescription(), within Transcript.php is going to have to change, but I've sort of gotten lost/confused at this point. Am I overthinking this, can I just pull the video descriptions in from a frontend only solution?

Thank you in advance for your help and insight.

1 Answer 1

0

I have managed to fix the issue, which is to say, get the intended result. Here's the code in case it's helpful to someone else.

video_description.phtml

<?php if ($block->getVideoDescription()): ?>

<?php
$video_array = $block->getVideoDescription();
$json_array = json_encode($video_array);
?>

<script type="text/javascript">
let orderedTranscripts = [];

const createTranscript = () => {
    const js_array = JSON.parse('<?php echo $json_array; ?>');

    let PV_datacodes = [];
    let video_datacodes = [...document.querySelectorAll('.product-video')];

    for (let i = 0; i < video_datacodes.length; i++) {
        let id = video_datacodes[i].getAttribute('data-code');
        PV_datacodes.push(id);
    }

    let transcripts = [];

    i = 0;
    while(i < PV_datacodes.length) {
        transcripts.push(js_array[i].description);
        i++;
    }
    // loop over each transcript in transcripts, assign key value to video_datacodes, push to orderedTranscripts array
    orderedTranscripts = [];

    for (let i = 0; i < transcripts.length; i++) {
        let obj = {};
        obj[video_datacodes[i].attributes[4].value] = transcripts[i];
        orderedTranscripts.push(obj);
    }

    let video_key = '';
    // check active video id, compare against orderedtranscripts key
    if(document.getElementsByClassName('fotorama__active')[0].classList.contains('fotorama-video-container')){
        video_key = document.getElementsByClassName('fotorama__active')[0].getElementsByClassName('product-video')[0].getAttribute('data-code');
    }
    // if video_key matches key in orderedTranscripts, return value
    for (let i = 0; i < orderedTranscripts.length; i++) {
        if (video_key === Object.keys(orderedTranscripts[i])[0]) {
            document.getElementsByClassName('fotorama__caption__wrap')[i].innerHTML = orderedTranscripts[i][video_key];
        }
    }
}

const createButton = () => {
    let transcript = document.createElement('article');
    transcript.innerHTML = `
        <a onclick="createTranscript()" style="margin: 0.5em; text-decoration: none;" class="button btn btn-warning">Show Transcript</a>
    `;
    transcript.style.cssText = 'display: none; visibility: hidden;';
    jQuery('.product.media').append(transcript);
}

const addListeners = () => {
    let elements1 = [...document.getElementsByClassName("fotorama__img")];
    let elements2 = [...document.getElementsByClassName("fotorama__thumb-border")];
    let elements = elements1.concat(elements2);
    Array.from(elements).forEach(element => {
        element.addEventListener('click', createTranscript);
    });
}

require(["jquery"], function () {
    jQuery(document).ready(function() {
        createButton();
        setTimeout(() => {
            addListeners();
        }, 3000);
    });
});
</script>

<?php endif; ?>

There may be a better way to do this, in fact there probably is, would love to hear about it if someone has an idea!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.