Compare commits

...

2 Commits

Author SHA1 Message Date
dan612
8cee39a6df Pushing overhaul. 2025-12-06 16:34:43 -05:00
calcu1on
09043d7884 Randomg things. 2025-10-15 22:49:16 -04:00
31 changed files with 42561 additions and 257 deletions

View File

@ -1,7 +1,5 @@
#!/usr/bin/env bash
# import all fighters.
ddev drush @self.local ev '\Drupal::service("ufc.import_fighters")->importFighters();';
ddev drush @self.local ev '\Drupal::service("ufc.import_fights")->importEvents();';
ddev drush @self.local ev '\Drupal::service("ufc.import_fights")->createFights();';
ddev drush @self ufc:import-fighters

8102
web/db.sql Normal file

File diff suppressed because one or more lines are too long

BIN
web/db/backup.sqlite Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}

View File

@ -0,0 +1,5 @@
name: DC React
type: module
description: React Plaground
package: DC React
core_version_requirement: ^10 || ^11

View File

@ -0,0 +1,3 @@
main:
js:
js/dist/main.min.js: { minified: true }

View File

@ -0,0 +1,21 @@
<?php
/**
* Implements hook_theme().
*
* Register a module or theme's theme implementations.
* The implementations declared by this hook specify how a particular render array is to be rendered as HTML.
*
* See: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21theme.api.php/function/hook_theme/8.2.x
*
* If you change this method, clear theme registry and routing table 'drush cc theme-registry' and 'drush cc router'.
*/
function dc_react_theme($existing, $type, $theme, $path) {
return [
'react_block' => [
'variables' => [
'data' => [],
],
],
];
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
import React, { Component } from 'react';
function Button(props) {
return <button className={"btn btn-" + props.classes}><a href={props.link}>{ props.text }</a></button>;
}
export default Button;

View File

@ -0,0 +1,16 @@
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Counter;

View File

@ -0,0 +1,14 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import Button from './components/Button';
import Counter from './components/Counter';
const container = document.getElementById('react-block');
const root = createRoot(container);
root.render(
<div>
<Button text="Click me" link="https://www.drupal.org" classes="primary" />
<Counter />
</div>
);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
{
"name": "dc_react",
"version": "1.0.0",
"description": "TO DEVELOP --- Finish %",
"main": "index.js",
"scripts": {
"build": "webpack",
"build:dev": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"prop-types": "^15.8.1",
"react": "^19",
"react-dom": "^19"
},
"devDependencies": {
"@babel/core": "^7.24.4",
"@babel/preset-env": "^7.24.4",
"@babel/preset-react": "^7.27.1",
"babel-loader": "^9.1.3",
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Drupal\dc_react\Plugin\Block;
use Drupal\Core\Block\BlockBase;
/**
* Provides a React app block.
*
* @Block(
* id = "react_block",
* admin_label = @Translation("React Block"),
* category = @Translation("React"),
* )
*/
class ReactBlock extends BlockBase {
/**
* {@inheritdoc}
*/
public function build() {
$build = [
'#theme' => 'react_block',
];
return $build;
}
}

View File

@ -0,0 +1,3 @@
{{ attach_library('dc_react/main') }}
<div id="react-block" class="container"></div>
<h4>This is dan saying hi!</h4>

View File

@ -0,0 +1,28 @@
const path = require('path');
const config = {
entry: {
main: ["./js/src/index.jsx"]
},
devtool:'source-map',
mode:'development',
output: {
path: path.resolve(__dirname, "js/dist"),
filename: '[name].min.js'
},
resolve: {
extensions: ['.js', '.jsx'],
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
include: path.join(__dirname, 'js/src'),
}
],
},
};
module.exports = config;

View File

@ -0,0 +1,5 @@
testing:
js:
js/testing.js: {}
dependencies:
- core/drupal

View File

@ -0,0 +1,5 @@
<?php
function dc_tests_preprocess_node(&$variables) {
$variables['#attached']['library'][] = 'dc_tests/testing';
}

View File

@ -0,0 +1,10 @@
((Drupal, once) => {
Drupal.behaviors.myBehavior = {
attach(context) {
let target = once('myBehavior', 'body');
target.forEach((t) => {
alert('Behavior attached test');
});
},
};
})(Drupal, once);

View File

@ -24,8 +24,12 @@ public function importFighters(): void {
// First check for the item in cache.
$fighter_list = \Drupal::cache()->get($this->cacheId);
if (!$fighter_list) {
$fighter_list = $fighter_importer->getListOfCurrentFighters();
\Drupal::cache()->set($this->cacheId, $fighter_list, time() + 86400);
/* $fighter_list = $fighter_importer->getListOfCurrentFighters(); */
$api_list = \Drupal::httpClient()->get('https://www.ufc.com/jsonapi/node/athlete')->getBody()->getContents();
$fighter_list = json_decode($api_list)->data;
dump($fighter_list);
exit();
\Drupal::cache()->set($this->cacheId, $fighter_list, time() + 300);
}
else {
$fighter_list = $fighter_list->data;

View File

@ -45,22 +45,7 @@ class FighterImporter {
* The base url for fighter lists.
* @var string
*/
const UFC_BASE = "https://www.ufc.com/athletes/all?filters%5B0%5D=weight_class%3";
/**
* All applicable divisions and their keys on UFC.com.
* @var array[]
*/
protected $divisions = [
'heavyweight' => "A11",
'light_heavyweight' => "A13",
'middleweight' => "A14",
'welterweight' => "A15",
'lightweight' => "A12",
'featherweight' => "A9",
'bantamweight' => "A8",
'flyweight' => "A10",
];
const UFC_BASE = "https://www.ufc.com/jsonapi/node/athlete";
/**
* Public constructor for Fighter Importer.
@ -80,62 +65,14 @@ public function __construct(
}
public function importFighters(): void {
$test_run = FALSE;
if ($test_run) {
// Overriding to test!!!
$fighter_name_text_on_ufc = "
Georges St-Pierre
";
$fighter = new Fighter($this->httpClient);
$fighter->first_name = 'scott';
$fighter->last_name = 'adams';
$fighter->scrapeDataFromFighterPage();
$fighter_clone = clone ($fighter);
unset($fighter_clone->fighter_page);
unset($fighter_clone->crawler);
dump($fighter_clone);
}
else {
$fighters_by_div = self::getListOfCurrentFighters();
// Process each fighter into system.
foreach ($fighters_by_div as $division => $fighters) {
$this->processDivision($division, $fighters);
}
}
}
/**
* Process a division.
*
* @param mixed $div
* @param mixed $fighters
*/
public static function processDivision($div, $fighters): void {
\Drupal::logger('ufc')->notice("Starting to update $div");
foreach ($fighters as $fighter_data) {
$fighter = new Fighter(\Drupal::httpClient());
$fighter->first_name = $fighter_data['firstname'];
$fighter->last_name = $fighter_data['lastname'];
$fighter->image = $fighter_data['image'];
$fighter->class = $div;
if (!$fighter->scrapeDataFromFighterPage($fighter_data['profile'])) {
\Drupal::logger('ufc')->alert("FAILED: $fighter->first_name $fighter->last_name to " . $fighter_data['profile']);
}
// Check if node exists, by title.
$fighter->createMediaEntityFromImage();
$title = $fighter->first_name . " " . $fighter->last_name;
$node_lookup = reset(\Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['title' => $title]));
if (!empty($node_lookup)) {
// Update instead of create.
$fighter->updatePlayerNode($node_lookup->id());
\Drupal::logger('ufc')->notice("$title updated successfully.");
}
else {
\Drupal::logger('ufc')->warning("No existing player found for $title...creating");
$fighter->createPlayerNode();
}
// Get JSON File from API.
$api_athletes = $this->cache->get('ufc_api_athletes');
if (!$api_athletes) {
echo "Go get api data!";
exit();
}
// This includes all fighters in data.
// Iterate over data to import all fighters.
}
/**
@ -160,7 +97,7 @@ public function getListOfCurrentFighters(): array {
*/
public function loopThroughFighterPages($base_url): void {
// Implement caching to store instead of needing fresh requests.
for ($i=0; $i<=100; $i++) {
for ($i=0; $i<=10; $i++) {
$ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15';
$headers = [
'referer' => true,
@ -169,81 +106,23 @@ public function loopThroughFighterPages($base_url): void {
'User-Agent' => $ua,
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding' => 'gzip, deflate, br',
'Cache-Control' => 'no-cache',
'Pragma' => 'no-cache',
'Referer' => 'https://www.ufc.com/athletes/all',
]
];
$url = $base_url . "&page=$i";
/* $cid = "ufc:" . $url; */
$request = $this->httpClient->request('GET', $url, $headers);
$content = $request->getBody()->getContents();
$url = $base_url . "&page=$i&_=" . microtime(true);
$response = $this->httpClient->request('GET', $url, $headers);
dump($url);
$content = $response->getBody()->getContents();
dump($response->getStatusCode());
$invalid_page = strpos($content, "No Result Found For");
if (!$invalid_page) {
\Drupal::logger('ufc')->notice("Extracting fighters from page $i.");
self::extractFighters($content);
continue;
}
break;
}
}
/**
* Extract fighters from an html string.
*/
public function extractFighters(string $input): void {
$fighter_list = [];
$crawler = new Crawler($input);
$athlete_flipcards = $crawler->filter('.c-listing-athlete-flipcard');
$fighter_names = $athlete_flipcards->each(function (Crawler $crawler, $i) {
return $crawler->filter('.c-listing-athlete__name')->text();
});
$fighter_profile_urls = $athlete_flipcards->each(function (Crawler $crawler, $i) {
return $crawler->filter('.e-button--black')->attr('href');
});
$fighter_images = $athlete_flipcards->each(function (Crawler $crawler, $i) {
$imgs = $crawler->filter('img')->each(function ($i) {
return $i->attr('src');
});
return $imgs;
});
$count_fighter_names = count($fighter_names);
$count_profile_urls = count($fighter_profile_urls);
$count_images = count($fighter_images);
// Make sure the arrays are all the same size.
assert((
($count_fighter_names == $count_profile_urls) &&
($count_profile_urls == $count_images)
));
foreach ($fighter_names as $key => $fighter) {
$fighter_names[$key] = [
'name' => $fighter,
'profile' => $fighter_profile_urls[$key],
'images' => $fighter_images[$key],
];
}
foreach ($fighter_names as $fighter_data) {
$name_no_spaces = str_replace(" ", "", $fighter_data['name']);
$weight_class_exists = array_key_exists($this->weightClass, $this->fighters);
$fighter_exists = NULL;
if ($weight_class_exists) {
$fighter_exists = array_key_exists($name_no_spaces, $this->fighters[$this->weightClass]);
}
if (!$fighter_exists) {
$split_name = explode(" ", $fighter_data['name'], 2);
$this->fighters[$this->weightClass][$name_no_spaces]['firstname'] = $split_name[0] ?? " ";
$this->fighters[$this->weightClass][$name_no_spaces]['lastname'] = $split_name[1] ?? " ";
$this->fighters[$this->weightClass][$name_no_spaces]['profile'] = $fighter_data['profile'];
}
if (!empty($fighter_data['images']) && count($fighter_data['images']) == 2) {
$this->fighters[$this->weightClass][$name_no_spaces]['image'] = $fighter_data['images'][0];
}
else {
$this->fighters[$this->weightClass][$name_no_spaces]['image'] = FALSE;
}
}
}
}

View File

@ -0,0 +1 @@
<h1>Hello World</h1>

File diff suppressed because one or more lines are too long

View File

@ -12,19 +12,19 @@
# This means that if you want to override any value of a parameter, the
# whole parameter array needs to be copied from
# sites/default/default.services.yml or from core/core.services.yml file.
parameters:
http.response.debug_cacheability_headers: true
services:
cache.backend.null:
class: Drupal\Core\Cache\NullBackendFactory
logger.channel.config_schema:
parent: logger.channel_base
arguments: [ 'config_schema' ]
config.schema_checker:
class: Drupal\Core\Config\Development\LenientConfigSchemaChecker
arguments:
- '@config.typed'
- '@messenger'
- '@logger.channel.config_schema'
tags:
- { name: event_subscriber }
# parameters:
# http.response.debug_cacheability_headers: true
# services:
# cache.backend.null:
# class: Drupal\Core\Cache\NullBackendFactory
# logger.channel.config_schema:
# parent: logger.channel_base
# arguments: [ 'config_schema' ]
# config.schema_checker:
# class: Drupal\Core\Config\Development\LenientConfigSchemaChecker
# arguments:
# - '@config.typed'
# - '@messenger'
# - '@logger.channel.config_schema'
# tags:
# - { name: event_subscriber }

View File

@ -0,0 +1,13 @@
name: Alert
props:
type: object
properties:
alertType:
type: string
title: Alert Type
description: 'The type of alert.'
slots:
alertText:
title: Alert Text
required: true
description: The test for the alert.

View File

@ -0,0 +1,21 @@
.alert-wrapper .field_alert_text {
padding: 20px 0;
text-align: center;
}
.alert.normal {
background-color: deepskyblue;
color: darkblue;
}
.alert.warning {
background-color: goldenrod;
color: black;
font-weight: bold;
}
.alert.danger {
background-color: lightpink;
color: darkred;
font-weight: bolder;
}

View File

@ -0,0 +1,3 @@
<div class="alert {{ alertType }}">
{% block alertText %}{% endblock %}
</div>

View File

@ -116,6 +116,10 @@ h4 {
color: var(--site-primary);
}
.btn {
padding: 0;
}
.btn-primary a {
background: var(--site-primary) !important;
color: var(--site-white);

View File

@ -1,3 +1,7 @@
.btn {
padding: 0;
}
.btn-primary a {
background: var(--site-primary) !important;
color: var(--site-white);

View File

@ -0,0 +1,26 @@
{#
* Component variables
*
* props:
* alerType
*
* slots
* alertText
*
#}
<div {{ attributes.addClass('alert-wrapper') }}>
{{ title_prefix }}
{{ title_suffix }}
{% set alertType = content.field_alert_type.0['#markup']|clean_class %}
{% embed 'dchadwick:alert' with {
alertType: alertType,
}%}
{% block alertText %}
<p>{{ content.field_alert_text }}</p>
{% endblock%}
{% endembed %}
</div>