I'm trying to display an image but I am running into the error of Not allowed to load local resource: file:///C:/xampp/htdocs/public/images/profile/jimmy/status/boned.jpg in the browser console. What I am trying to do is use the base path provided by Zend Framework 2 but I'm retrieving the images in the model so (as far as I know), I can't use $this->basePath() like I would in the view.
This is my json string I am returning but would like to just be able to return /images/profile/jimmy/status/boned.jpg and whatever other images are in there.
I'm getting all the files outside of the directory 'status'. I am trying to get the files inside the status directory. When I did a var_dump this is what I get string(43) "C:\xampp\htdocs/public/images/profile/jimmy" I'm unclear why it is omitting the status directory after '/jimmy'
json string being returned:
{"feed":{"username":"Timmy","status":["this is jimmy, test"],"images":["videos","status","sithtoon.jpg","sith.jpg","edited_photos","diploma.jpg","current","albums","Screenshot_2016-08-09_21_28_13_361272.jpg","Screenshot_2016-08-05_17_55_48_500802.jpg","515gIIJ-Imgur.png",".htaccess"]}}
Here is the relevant PHP code (in the model):
public function listFriendsStatus()
{
$user_id = $this->getUserId()['id'];
// get the friend ids based on user id
// and then compare the friend id to the id in status table
$friend_query = new Select('friends');
$friend_query->columns(array('friend_id'))
->where(array('user_id' => $user_id));
$query = $this->sql->getAdapter()->query(
$this->sql->buildSqlString($friend_query),
Adapter::QUERY_MODE_EXECUTE
);
if ($query->count() > 0) {
$friend_id = array();
foreach ($query as $result) {
$friend_id[] = $result['friend_id'];
}
$status = new Select('status');
$status->columns(array('status'))
->where(array('id' => $friend_id));
$status_query = $this->sql->getAdapter()->query(
$this->sql->buildSqlString($status),
Adapter::QUERY_MODE_EXECUTE
);
if ($status_query->count() > 0) {
// check if a image was used
$members = new Select('members');
$members->columns(array('username'))
->where(array('id' => $friend_id));
$image_query = $this->sql->getAdapter()->query(
$this->sql->buildSqlString($members),
Adapter::QUERY_MODE_EXECUTE
);
if ($image_query->count() > 0) {
foreach ($image_query as $value) {
if (is_dir(getcwd() . '/images/profile/' . $value['username'] . '/status/')) {
$status_dir = pathinfo(getcwd() . '/images/profile/' . $value['username'] . '/status/');
}
}
$images = array();
chdir($status_dir['dirname']);
var_dump($status_dir['dirname']);
// retrieve the image inside the status directory
foreach (array_diff(scandir($status_dir['dirname'], 1), array('.', '..')) as $values) {
$images[] = $values;
}
} else {
throw new FeedException("The user does not exist in the user table.");
}
$status = array();
// get all the statuses
foreach ($status_query as $rows) {
$status[] = $rows['status'];
}
return array('username' => ucfirst($value['username']), 'status' => $status, 'images' => $images); // how to just get the basePath path with zf2
} else {
throw new FeedException("No status was found for your friends.");
}
} else {
throw new FeedException(sprintf("Could not locate any friends for %s", $this->user));
}
}
controller code:
public function getfriendstatusAction()
{
$layout = $this->layout();
$layout->setTerminal(true);
$view_model = new ViewModel();
$view_model->setTerminal(true);
try {
echo json_encode(array('feed' => $this->getStatusService()->listFriendsStatus()));
} catch (FeedException $e) {
echo json_encode(array('fail' => $e->getMessage()));
}
return $view_model;
}
jquery code:
$.getJSON('/members/feed/get-friend-status', function(data) {
$.each(data, function(i, item) {
$('.w3-container.w3-card-2.w3-white.w3-round.w3-margin').find('h4').html(data[i].username);
$('.w3-container.w3-card-2.w3-white.w3-round.w3-margin').find('p').html(data[i].status);
$('.w3-container.w3-card-2.w3-white.w3-round.w3-margin').find('img').attr('src', data[i].images);
});
}).fail(function(response) {
console.log(response);
});
I've been trying to use other directory functions provided with PHP but if I try anything, I run into the error directory could not be found. Basically what I am trying to do is use the similiar approach of $this->basePath() but in a model.
I hope that is clear enough..
Thanks!
Here is a screenshot of what I'm getting and how I want to get the status directory, not the directory outside of it.
I have an idea.
In your code is:
$status_dir = pathinfo(getcwd() . '/images/profile/' . $value['username'] . '/status/');
// ..............
chdir($status_dir['dirname']);
var_dump($status_dir['dirname']);
Try:
var_dump($status_dir);
I guess 'status' will be in 'basename' and / or in 'filename'
pathinfo gets last segment of argument string path as 'basename'.
Pathinfo only parses string as path and return array info, don't check it for isDir or isFile. Your correct chdir should looks like chdir($status_dir['dirname'] . '/' . $status_dir['basename'] ); if you need use of pathinfo.
In other words: dirname of 'images/profile/jimmy/status' is 'images/profile/jimmy' and its a reason why you don't see status in var_dump($status_dir['dirname']) and why chdir($status_dir['dirname']) not working correctly.
Related
Need to upload Files in core MVC: successfully uploaded. Now I am successfully passing my array of selected file from calling function to controller. How can I use that array in controller. Its showing : Notice: Trying to get property of non-object in controller(i.e. inside foreach)
controller:
function gallery($real_name) {
/*echo "<pre>"; print_r($real_name); die();*/
foreach($real_name as $k=>$v) {
// $sql = "INSERT INTO gallery SET image = '".$v->image."'"; /*echo "{$k} => {$v}";*/
// /*print_r($sql); die;*/ } die();
// if($this->DB->exeQuery($sql)) { return true; } }
}
}
No need loop here. Direct use $real_name with indexes to access file info.
$sql = 'INSERT INTO gallery SET image = "' . $real_name['file_name'] . '"';
Just in Gallery function controller add:
function gallery($real_name) {
$sql = "INSERT INTO gallery SET image = '".$real_name."'";
// instead of foreach just write above statement
if($this->DB->exeQuery($sql)) { //firing the query
return true;
}
}
I am build uploader images and store it into database, I already can upload many images to folder, but I can't insert all images name that uploaded, and I don't know how to insert into database, first I have put commend on my code below when error occur, second I don't know the query to put it in database if the image count is different e.g 1-10 images, last question, if I do query "SELECT id..." and I want to return it, is there method to return it into string or int? If I use row() it will return stdClass object. please help me,
below is my code:
controller :
$this->load->library("myupload", "form_validation");
$this->load->model("testModel");
$barangImage = array();
if($this->input->post("formSubmit")) {
$this->form_validation->set_rules("nama", "Nama", "required|trim");
if($this->form_validation->run()) {
$insertData = array(
"nama" => $this->input->post("nama")
);
if($id = $this->testModel->add($insertData)) {
//print_r($id);
if(isset($_FILES) && $image = $this->myupload->uploadFile($_FILES)) {
//$image here is already fill with all images name
if(isset($image["error"]) && $image["error"]) {
echo $image["error"];
}else {
foreach($image as $img) {
$barangImage = array(
"gambar" => $img,
"barangid" => $id
);
}
//but when i put into barangImage,
//it only stored last image name
print_r($barangImage);
//output `Array ( [gambar] => 2.JPG [barangid] => Array ( [id] => 52 ) )`
}
}
if($id = $this->testModel->add_images($barangImage)) {
echo "SUCCESS !!!";
}else {
echo "FAIL INSERT IMAGES!!!";
}
}else {
echo "FAIL INSERT DATA NAMA";
}
}else {
echo "FAIL VALIDASI RUN";
}
}
model :
public function add($newData){
$this->db->insert("cobabarang", $newData);
$nama = $newData["nama"];
$id = $this->db->query("SELECT id FROM cobabarang WHERE nama = \"$nama\"");
return $id->row_array();
}
public function add_images($newImage) {
//$this->db->insert("cobagambar", $newImage);
$id = $newImage["barangid"]["id"];
$gambar = $newImage["gambar"];
$this->db->query("INSERT INTO cobagambar(barangid, gambar1) VALUES($id, \"$gambar\")");
}
there is an error here:
foreach($image as $img)
{
$barangImage = array(
"gambar" => $img,
"barangid" => $id
);
}
change the $barangImage to $barangImage[]
when you put the images into database i suggest that using json_encode($barangImage), and then json_decode($images-json-string) when you going to use the images.
There is something wrong with your foreach loop
foreach($image as $img) {
$barangImage = array(
"gambar" => $img //might be img['img'] I guess $img is again an array...you hvae to check that
"barangid" => $id //might be $img['id']check on this too..will be $img['id'] I guess
);
}
My guess is that $img is again an array with some keys. You really need to check on that And you can directly call the insert function in that foreach loop itself like this,
foreach($image as $img) {
$barangImage = array(
"gambar1" => $img['img'], //I guess $img is again an array...you hvae to check that
"barangid" => $img['id'] //check on this too..will be $img['id'] I guess
);
$id = $this->testModel->add_images($barangImage));
}
NOTE: The keys in your array barangImage must be column name in the table. i.e
gambar1 and barangid will be your column names. so you can directly use codeIgniter's active records.
Just change your add_images function
public function add_images($newImage) {
$this->db->insert("cobagambar", $newImage);
}
I am trying to upload an external list of "groups" to add to my custom Joomla 3 component. I have created a CSV file and written a few functions that I hope will do it. I have created a custom button to start the task in my "groups" view.
When I push the button I get an SQL error that has absoloutle nothing to do with the functions so I have tried debugging and when the button is pressed its not even getting to my controller task before the sql error. I am so confused as to why.
This is the code I have
view.html.php TestViewGroups
JToolBarHelper::custom('group.uploadsave', '', '', 'Upload and Save', false);
TestControllerGroup
protected function uploadsave() {
$detail_headers = array(
'agm_date',
'preferred_media'
);
$rows = array_map('str_getcsv', file('groupdata.csv'));
$header = array_shift($rows);
foreach ($rows as $row) {
$entry = array_combine($header, $row);
foreach ($entry as $key => $value) {
if(in_array($key, $detail_headers)){
$details[$key]= $value;
unset($entry[$key]);
}
}
$entry['details'] = $details;
$this->saveUploaded($entry);
}
// Redirect to the list screen.
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_list
. $this->getRedirectToListAppend(), false
)
);
}
protected function saveUploaded($dataIn = array()) {
$app = JFactory::getApplication();
$lang = JFactory::getLanguage();
$model = $this->getModel();
$table = $model->getTable();
$data = $dataIn;
$checkin = property_exists($table, 'checked_out');
// Determine the name of the primary key for the data.
if (empty($key))
{
$key = $table->getKeyName();
}
// To avoid data collisions the urlVar may be different from the primary key.
if (empty($urlVar))
{
$urlVar = $key;
}
$recordId = $this->input->getInt($urlVar);
// Populate the row id from the session.
$data[$key] = $recordId;
if (!$model->save($validData))
{
// Redirect back to the edit screen.
$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()));
$this->setMessage($this->getError(), 'error');
}
if ($checkin && $model->checkin($validData[$key]) === false)
{
// Save the data in the session.
$app->setUserState($context . '.data', $validData);
// Check-in failed, so go back to the record and display a notice.
$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()));
$this->setMessage($this->getError(), 'error');
}
$this->setMessage(
JText::_(
($lang->hasKey($this->text_prefix . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS')
? $this->text_prefix
: 'JLIB_APPLICATION') . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS'
)
);
}
I am not using this as a regular function, its just a once off to upload the data initially.
The SQL error I am getting is like it is trying to load a list of groups?? not anything to do with the save function at all.
The saveUploaded is a similar function to the initial save function.
Thanks :-)
**** Edit *****
I have just followed the task through with debug and its getting to the execute task methotd of JControllerLegacy and because the task is not defined in the task map its defaulting to display, hence the SQL error trying to load a group when it doesn't have an ID. Do I need to now register a task in the task map before it will pick it up?
I am officially an idiot! When I just logged back on to see if anyone had responded I saw that I had declared the function as a protected function!! dir! I just copied and pasted from another function and forgot to change its access. I also made a few other changes and now it works quite well!
public function uploadsave() {
// An array of headers that will need to be entered into a seperate array to allow entry as JSON
$detail_headers = array(
'agm_date',
'preferred_media'
);
$app = JFactory::getApplication();
$lang = JFactory::getLanguage();
$model = $this->getModel();
$path = JPATH_COMPONENT . '/controllers/groupdata.csv';
//Load the file and pass each line into an array.
$rows = array_map('str_getcsv', file($path));
//Take out the first line as it is the headers.
$header = array_shift($rows);
//turn each of the arrays into an entry
foreach ($rows as $row) {
$entry = array_combine($header, $row);
foreach ($entry as $key => $value) {
//separate each of the entries that need to be entered into an array to be stored as JSON
if(in_array($key, $detail_headers)){
$details[$key]= $value;
unset($entry[$key]);
}
}
$entry['details'] = $details;
$recordId = 'id';
// Populate the row id from the session.
$entry[$key] = $recordId;
//Save each one
if (!$model->save($entry))
{
// Redirect back to the edit screen.
$this->setError(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()));
$this->setMessage($this->getError(), 'error');
return false;
}
$this->setMessage(
JText::_(
($lang->hasKey($this->text_prefix . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS')
? $this->text_prefix
: 'JLIB_APPLICATION') . ($recordId == 0 && $app->isSite() ? '_SUBMIT' : '') . '_SAVE_SUCCESS'
)
);
}
// Redirect to the list screen.
$this->setRedirect(
JRoute::_(
'index.php?option=' . $this->option . '&view=' . $this->view_list
. $this->getRedirectToListAppend(), false
)
);
}
I am having a very difficult time getting this to work how I want. I am looking to grab all of the videos from a playlist. Currently I can retrieve 20 but there are some playlists that contain over 100 videos. This is where I am having a problem. I am using the following code I found from another user on here because I have exhausted everything I can think of.
This starts the process. Note that I am calling the XML feed through a specific URL as there is minimal information on Googles Dev site for what I am trying to do.
public function saveSpecificVideoFeed($id) {
$url = 'https://gdata.youtube.com/feeds/api/playlists/' . $id . '?v=2';
$feed = $this->yt->getPlaylistVideoFeed($url);
$this->saveEntireFeed($feed, 1);
}
This is what I am passing the above function to:
public function saveEntireFeed($videoFeed, $counter) {
foreach ($videoFeed as $videoEntry) {
if (self::saveVideoEntry($videoEntry)) {
$this->success++;
} else {
$this->failed++;
}
$counter++;
}
// See whether we have another set of results
try {
$videoFeed = $videoFeed->getNextFeed();
} catch (Zend_Gdata_App_Exception $e) {
echo $e->getMessage() . "<br/>";
echo "Successfuly Pulled: <b>" . $this->success . "</b> Videos.<br/>";
echo "Failed to Pull: <b>" . $this->failed . "</b> Videos.<br/>";
echo "You Tryed to Insert: <b>" . $this->duplicate . "</b> Duplicate Videos.";
return;
}
if ($videoFeed) {
self::saveEntireFeed($videoFeed, $counter);
}
}
Here is how I am saving the videos individually:
private function saveVideoEntry($videoEntry) {
if (self::videoExists($videoEntry->getVideoId())) {
// Do nothing if it exists
} else {
$videoThumbnails = $videoEntry->getVideoThumbnails();
$thumbs = null;
foreach ($videoThumbnails as $videoThumbnail) {
$thumbs .= $videoThumbnail['url'] . ',';
}
$binds = array(
'title' => $videoEntry->getVideoTitle(),
'videoId' => $videoEntry->getVideoId(),
'updated' => $videoEntry->getUpdated(),
'description' => $videoEntry->getVideoDescription(),
'category' => $videoEntry->getVideoCategory(),
'tags' => implode(", ", $videoEntry->getVideoTags()),
'watchPage' => $videoEntry->getVideoWatchPageUrl(),
'flashPlayerUrl' => $videoEntry->getFlashPlayerUrl(),
'duration' => $videoEntry->getVideoDuration(),
'viewCount' => $videoEntry->getVideoViewCount(),
'thumbnail' => $thumbs,
);
$sql = "INSERT INTO $this->tblName (title, videoId, updated, description, category, tags, watchPage, flashPlayerUrl, duration, viewCount, thumbnail)
VALUES (:title, :videoId, :updated, :description, :category, :tags, :watchPage, :flashPlayerUrl, :duration, :viewCount, :thumbnail)";
$sth = $this->db->prepare($sql);
foreach ($binds as $key => $value) {
if ($value == null) {
$value = '';
}
$sth->bindValue(":{$key}", $value);
}
if ($sth->execute()) {
return true;
} else {
print_r($sth->errorInfo());
return false;
}
}
}
This is what I get from browser output to let me know in an easy to read format what ive gotten from the pull:
Table has been created continuing with extraction. No link to next set
of results found. Successfully Pulled: 20 Videos. Failed to Pull: 0
Videos. You Tried to Insert: 0 Duplicate Videos.
This however is a playlist with 36 videos so my problem is accessing the remaining videos. Is there an easier not so documented way to do this? Any help would be greatly appreciated.
I have already tried using the max-results and the start-index elements in the request URL and increasing them to the needed values when looping through, this however has no effect on the XML output from the YouTube API.
Any help would be greatly appreciated.
So i decided to go a different route and use the following code:
<?php
include('HttpCurl.php');
class YouTube {
public $url;
private $content;
private $videoId = array();
private $Http,$Doc;
function __construct() {
$this->Http = new HttpCurl();
$this->Doc = new DOMDocument();
}
/*
* Sets url to strip the videos from;
* Insert the full URL for the videos YouTube playlist like:
* http://www.youtube.com/watch?v=saVE7pMhaxk&list=EC6F914D0CF944737A
*/
public function setUrl($url) {
$this->url = $url;
if ($this->check($this->url)) {
$this->getPage();
}
}
private function check($item) {
if (isset($item)) {
return true;
} else {
return false;
}
}
/*
* Grab the page that is needed
*/
private function getPage() {
$this->content = $this->Http->getContent($this->url);
if($this->check($this->content)) {
$this->getPlaylistVideos();
}
}
/*
* Parse page for desired result in our case this will default to the
* playlist videos.
*/
private function getPlaylistVideos() {
$this->Doc->preserveWhiteSpace = false;
// Load the url's contents into the DOM (the # supresses any errors from invalid XML)
if (#$this->Doc->loadHTML($this->content) == false) {
die("Failed to load the document you specified.: " . $page);
}
$xpath = new DOMXPath($this->Doc);
if ($hrefs = $xpath->query("//ol[#id='watch7-playlist-tray']//li")) {
//echo "<br/>Grabbing Videos and playlists!";
//Loop through each <a> and </a> tag in the dom and add it to the link array
//$count = count($this->data['link']);
foreach ($hrefs as $link) {
$this->videoId[] = $link->getAttribute('data-video-id');
}
var_dump($this->videoId);
}
}
}
So not quite what I want but returns all of the ids for the videos so that I can parse them for full data from the YouTube API.
So I have a custom Drupal module that outputs a formatted version of the song node's data based on a node id in the path (load/song/NID). This function works fine, and when I look at the url in my browser, I see that everything has loaded perfectly.
My module's code:
function load_song($nid){
$node = node_load($nid);
$songname = $node->title;
$albumid = $node->field_album['und'][0]['nid'];
$album = node_load($albumid);
$file = $album->field_cover['und'][0];
//Loads the album filepath from the file array returned above
$filepath = $file['uri'];
//The path returned is something like "public://file.jpg"
$filepath = str_replace("public://", "http://mysite.com/sites/default/files/styles/thumbnail/public/", $filepath);
//I then set a variable (imgurl) to the formatted filepath
$imgurl = $filepath;
$artistid = $album->field_artist['und'][0]['nid'];
$artist = node_load($artistid);
$artistname = $artist->title;
echo 'I output the variables + formatting here';
}
With the output, I then load it in my page.tpl.php file in Drupal using the jQuery .load function. My code:
function loadSongInfo(id) {
$("#current-song").html('Loading').load('http://mysite.com/load/song/' + id);
}
So with this input, what I get is the data from the url (which is perfectly formatted), and the other variables I load (artist name, song name, etc) working fine. However, where I have the filepath, all I get is an empty string.
This of course confuses the hell out of me, because it works fine in my browser, but when I call the function in jQuery, it loads all the other variables fine, except for the filepath.
I've tried (and got unsuccessful results):
Casting the variable $filepath to a string using three different methods
(I thought it might be something weird with the url) I replaced the filepath variable with just the static string of it ("http://mysite.com/sites/default/files/styles/thumbnail/public/file.jpg"), which returned the correct result, but still fails with the actual variable
var_dump
print_r
Does anyone have any idea why this isn't working?
Mymodule
function mymodule_menu(){
$items = array();
$items['js/song'] = array(
'page callback' => 'load_song',
'type' => MENU_CALLBACK,
'access arguments' => array('access content')
);
}
function load_song() {
$nid = $_POST['nid'];
$node = node_load($nid);
/*
* Check for node existing
* Return response.error if not loaded
*/
if(!$node->nid){
drupal_json(array('error' => t('Some text for error')));
die();
}
$songtitle = $node->title;
$albumid = $node->field_album['und'][0]['nid'];
$album = node_load($albumid);
$file = $album->field_cover['und'][0];
// Loads the album filepath from the file array returned above
$filepath = $file['uri'];
// The path returned is something like "public://file.jpg"
$filepath = str_replace("public://", "http://mysite.com/sites/default/files/styles/thumbnail/public/", $filepath);
// I then set a variable (imgurl) to the formatted filepath
$imagepath = $filepath;
$artistid = $album->field_artist['und'][0]['nid'];
$artist = node_load($artistid);
$artistname = $artist->title;
$object = array(
'song_title' => l($songtitle, 'node/'. $node->nid),
'image_path' => $imagepath,
'artist_name' => l($artistname, $artist->nid)
);
drupal_json(array('data' => $object));
die();
}
Javascript:
Drupal.behaviors.SongInit = function(context){
$("#current-song").html('Loading...').load("/load/song", {
nid : id
}, function(response, status, xhr) {
if (status == 'error') {
var msg = Drupal.t("Sorry but there was an error: ");
$("#current-song").html(msg + xhr.status + " " + xhr.statusText);
}
if (response.error) {
var msg = Drupal.t("Sorry but there was an error: ");
$("#current-song").html(msg);
}
else {
var msg = response.data.song_title + '<br />';
var msg = '<img src=/"' + response.data.image_path + ' /><br />';
var msg = response.data.artist_name + '<br />';
$("#current-song").html(msg);
Drupal.attachBehaviors(context);
}
});
}